Scala: Saving/writing XML to a file

Problem: You want to write XML data to a file in a Scala application, such as saving application data or configuration information to a file.

Solution

Use the scala.xml.XML.save method to write a Scala literal to a file. Given this XML literal:

// create an XML variable
val portfolio = 
  <portfolio>
    <stocks>
      <stock>AAPL</stock>
      <stock>AMZN</stock>
      <stock>GOOG</stock>
    </stocks>
    <reits>
      <reit>Super REIT 1</reit>
    </reits>
  </portfolio>

write the literal to file with the save method:

// save the XML to a file
scala.xml.XML.save("portfolio.xml", portfolio)

This creates a plain-text file named portfolio.xml in the current directory, containing the XML literal shown.

As with any file-writing code, beware that XML.save can throw an exception:

scala> scala.xml.XML.save("/foo/bar/baz", portfolio)
java.io.FileNotFoundException: /foo/bar/baz (No such file or directory)

Additional save parameters

The save method lets you specify other parameters, including the encoding to use, whether or not to write an XML declaration, and whether or not to write a DOCTYPE declaration.

To write the data to a file with encoding information, use this approach:

XML.save("portfolio.xml", portfolio, "UTF-8", true, null)

This results in the following header being added to the file:

<?xml version='1.0' encoding='UTF-8'?>

To add a DOCTYPE to the file, first import the necessary classes:

import scala.xml.dtd.{DocType, PublicID}

Then create a DocType instance, and save the file with that instance:

val doctype = DocType("html",
  PublicID("-//W3C//DTD XHTML 1.0 Strict//EN",
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"),
  Nil)

XML.save("portfolio.xml", portfolio, "UTF-8", true, doctype)

With this configuration, the following DOCTYPE line is added to the output file:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

The scala.xml package also includes a Utility object with a small collection of useful methods that let you sort node attributes, trim elements, remove comments, and more.

Pretty printing

If it’s important that the XML can be easily read by a human being, it’s best to use the PrettyPrinter class to make sure the XML is “human readable.” But because the PrettyPrinter returns a String, you’ll need to write it to a file using another method. I have my own FileUtils class, so the process looks like this:

val portfolio =
  <portfolio>
    <stocks>
      <stock>AAPL</stock><stock>AMZN</stock><stock>GOOG</stock>
    </stocks>
    <reits><reit>Super REIT 1</reit></reits>
  </portfolio>

// 80 characters wide, 2 character indentation
val prettyPrinter = new scala.xml.PrettyPrinter(80, 2)
val prettyXml = prettyPrinter.format(portfolio)
FileUtils.save("portfolio.xml", prettyXml)

See Also