Skip to content
Aaron S. Hawley edited this page Oct 16, 2017 · 24 revisions

The following documentation assumes you're familliar with and already using both the Scala programminag language and the sbt build tool:

In Scala 2.11 and later, add the following to your build.sbt file's libraryDependencies:

"org.scala-lang.modules" %% "scala-xml" % "1.0.6"

You can query XML values with an XPath-like syntax:

val id = book \@ "id"
id: String = b20234

val text = book.text
text: String = Magic of scala-xml

XML more often has sub-elements:

val books = <books>
  <book id="b1615">Don Quixote</book>
  <book id="b1867">War and Peace</book>
</books>

Retrieving the child elements is possible, but a little more complicated:

val titles = (books \ "book").map(_.text).toList
titles: List[String] = List(Don Quixote, War and Peace)

Many return types of scala-xml are are Scala collections. If you aren't familiar with Scala collections, you should read the documentation for Scala collections.

Finding the text of an XML element by its id

val quixote = (books \ "book").find(book => (book \@ "id") == "b1615").map(_.text)
quixote: Option[String] = Some(Don Quixote)

Most operations on collections can use Scala's for-comprehension. For example, consider the following XML data representing a purchase order:

<?xml version="1.0"?>
<purchaseOrder orderDate="1999-10-20">
  <shipTo country="US">
    <name>Alice Smith</name> <street>123 Maple Street</street>
    <city>Mill Valley</city> <state>CA</state> <zip>90952</zip>
  </shipTo>
  <billTo country="US">
    <name>Robert Smith</name> <street>8 Oak Avenue</street>
    <city>Old Town</city> <state>PA</state> <zip>95819</zip>
  </billTo>
  <comment>Hurry, my lawn is going wild!</comment>
  <items>
    <item partNum="872-AA">
      <productName>Lawnmower</productName> <quantity>1</quantity>
      <USPrice>148.95</USPrice> <comment>Confirm this is electric</comment>
    </item>
    <item partNum="926-AA">
      <productName>Baby Monitor</productName> <quantity>1</quantity>
    <USPrice>39.98</USPrice> <shipDate>1999-05-21</shipDate>
    </item>
  </items>
</purchaseOrder>

This example is derived from similar code in the article "Scalable Programming Abstractions for XML Services" by Burak Emir, Sebastian Maneth and Martin Odersky. Here a file is loaded, and prices are retrieved for each item and summed together.

val doc = XML.loadFile("po.xml")
var total = BigDecimal(0).setScale(2, scala.math.BigDecimal.RoundingMode.HALF_UP)
for {
  item  <- doc \\ "item"
  price <- item \ "USPrice"
} yield {
  println("partnum: " + item \@ "partNum")
  total += price.text.toDouble
}
println(s"Grand total " + total)

The program will output:

partnum: 872-AA
partnum: 926-AA
Grand total 188.93

To open XML from files use scala.xml.XML:

val books = scala.xml.XML.loadFile("books.xml")

To write XML to a file:

scala.xml.XML.save("books.xml", books)

To format XML use the scala.xml.PrettyPrinter to configure the line length and indentation level:

val pp = new scala.xml.PrettyPrinter(24, 4)
pp.format(books)
<books>
    <book id="b1615">
        Don Quixote
    </book>
    <book id="b1867">
        War and Peace
    </book>
</books>
Clone this wiki locally