Decoding nodes as tuples

We’ve seen in a previous tutorial how to extract primitive types from XML documents. Often, however, these primitive values need to be assembled in more complex types, such as tuples. kantan.xpath provides a simple way of doing so.

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 an (Int, Boolean) tuple. In order to do that, we need to declare an implicit NodeDecoder[(Int, Boolean)] value: this will be automatically picked up by kantan.xpath and used when we request XML nodes to be interpreted as (Int, Boolean) values.

The easier way to declare a NodeDecoder instance for tuples is to use the dedicated tuple method, which takes one XPath expression per field to extract:

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

implicit val elementDecoder: NodeDecoder[(Int, Boolean)] = NodeDecoder.tuple[Int, Boolean](xp"./@id", xp"./@enabled")

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

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

Other tutorials: