Decoding nodes as case classes

We’ve seen in a previous tutorial how to extract tuples from XML documents. The next step up from tuples is case classes, which work in a very similar fashion.

In order to show how that works, we’ll first need some sample XML data, which we’ll get from this project’s resources:

val rawData: java.net.URL = getClass.getResource("/simple.xml")

This is what we’re working with:

scala.io.Source.fromURL(rawData).mkString
// res0: String = """<root>
//     <element id="1" enabled="true"/>
//     <element id="2" enabled="false"/>
//     <element id="3" enabled="true"/>
//     <element id="4" enabled="false"/>
// </root>"""

We’ll be trying to turn each element node into values of the following type:

final case class El(id: Int, enabled: Boolean)

In the same way that we had to declare a NodeCoder[(Int, Boolean)] to decode tuples, we’ll need a NodeDecoder[El] for this case class, which we can easily create through the decoder method:

import kantan.xpath._
import kantan.xpath.implicits._

// There is no need to specify type parameters here, the Scala compiler works them out from El.apply.
implicit val elDecoder: NodeDecoder[El] = NodeDecoder.decoder(xp"./@id", xp"./@enabled")(El.apply)

Now that we have told kantan.xpath how to decode an XML node to an instance of El, we can simply call evalXPath with the right type parameters:

rawData.evalXPath[List[El]](xp"//element")
// res1: XPathResult[List[El]] = Right(
//   value = List(
//     El(id = 1, enabled = true),
//     El(id = 2, enabled = false),
//     El(id = 3, enabled = true),
//     El(id = 4, enabled = false)
//   )
// )

Other tutorials: