Skip to content

Commit

Permalink
Add support for pretty printing XML
Browse files Browse the repository at this point in the history
  • Loading branch information
satabin committed Jan 22, 2024
1 parent a2b202f commit aeb99a3
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 5 deletions.
11 changes: 11 additions & 0 deletions xml/src/main/scala/fs2/data/xml/Attr.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,15 @@ package fs2
package data
package xml

import cats.Show
import cats.syntax.all._

case class Attr(name: QName, value: List[XmlEvent.XmlTexty])

object Attr {

implicit val show: Show[Attr] = Show.show { case Attr(name, value) =>
show"""$name="${value.foldMap(_.render)}""""
}

}
37 changes: 32 additions & 5 deletions xml/src/main/scala/fs2/data/xml/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,39 @@ package object xml {
* without additional (or original) whitespace and with empty tags being collapsed to the short self-closed form <x/>
* if collapseEmpty is true. Preserves chunking, each String in the output will correspond to one event in the input.
*/
@deprecated(message = "Use `fs2.data.xml.render.raw() instead.`", since = "fs2-data 1.11.0")
def render[F[_]](collapseEmpty: Boolean = true): Pipe[F, XmlEvent, String] =
_.zipWithPrevious.map {
case (_, st: XmlEvent.StartTag) => st.render(collapseEmpty)
case (Some(XmlEvent.StartTag(_, _, true)), XmlEvent.EndTag(_)) if collapseEmpty => ""
case (_, event) => event.show
}
render.raw(collapseEmpty)

object render {

/**
* Render the incoming xml events to their string representation. The output will be concise,
* without additional (or original) whitespace and with empty tags being collapsed to the short self-closed form <x/>
* if collapseEmpty is true. Preserves chunking, each String in the output will correspond to one event in the input.
*/
def raw[F[_]](collapseEmpty: Boolean = true): Pipe[F, XmlEvent, String] =
_.zipWithPrevious.map {
case (_, st: XmlEvent.StartTag) => st.render(collapseEmpty)
case (Some(XmlEvent.StartTag(_, _, true)), XmlEvent.EndTag(_)) if collapseEmpty => ""
case (_, event) => event.show
}

/**
* Render the incoming xml events intot a prettified string representation.
* _Prettified_ means that nested tags will be indented as per `indent` parameter
* and text data (except for `CDATA`, which remains untouched) is indented to the current
* indentation level after each new line.
*
* This pipe can be used when whitespace characters are not relevant to the application
* and to make it more readable to human beings.
*/
def pretty[F[_]](collapseEmpty: Boolean = true,
indent: String = " ",
attributeThreshold: Int = 3): Pipe[F, XmlEvent, String] =
Renderer.pipe(collapseEmpty, indent, attributeThreshold)

}

val ncNameStart = CharRanges.fromRanges(
('A', 'Z'),
Expand Down

0 comments on commit aeb99a3

Please sign in to comment.