Xml in Scala

import scala.xml._

// Plant will be mapped to XML. We use case classes in Scala for easy XML serialization.
// The @XmlAttributes annotation is used to specify XML attributes.
case class Plant(@XmlAttribute id: Int, name: String, origin: Seq[String]) {
  override def toString: String = s"Plant id=$id, name=$name, origin=${origin.mkString("[", ", ", "]")}"
}

object XMLExample extends App {
  val coffee = Plant(27, "Coffee", Seq("Ethiopia", "Brazil"))

  // Emit XML representing our plant; using a pretty-printer for more
  // human-readable output.
  val xml = scala.xml.Utility.trim(
    <plant id={coffee.id.toString}>
      <name>{coffee.name}</name>
      {coffee.origin.map(o => <origin>{o}</origin>)}
    </plant>
  )
  println(new PrettyPrinter(80, 2).format(xml))

  // To add a generic XML header to the output, prepend it explicitly.
  println("<?xml version='1.0' encoding='UTF-8'?>")
  println(new PrettyPrinter(80, 2).format(xml))

  // Use XML.loadString to parse a string of XML into a data structure.
  // If the XML is malformed or cannot be mapped onto Plant, a descriptive error
  // will be thrown.
  val parsedXml = XML.loadString(xml.toString())
  val parsedPlant = Plant(
    (parsedXml \@ "id").toInt,
    (parsedXml \ "name").text,
    (parsedXml \\ "origin").map(_.text)
  )
  println(parsedPlant)

  val tomato = Plant(81, "Tomato", Seq("Mexico", "California"))

  // In Scala, we can use nested XML literals to create complex structures
  val nesting = 
    <nesting>
      <parent>
        <child>
          {Seq(coffee, tomato).map(p =>
            <plant id={p.id.toString}>
              <name>{p.name}</name>
              {p.origin.map(o => <origin>{o}</origin>)}
            </plant>
          )}
        </child>
      </parent>
    </nesting>

  println(new PrettyPrinter(80, 2).format(nesting))
}

This Scala code demonstrates XML handling using the built-in scala.xml package. Here’s a breakdown of the key points:

  1. We define a Plant case class to represent our data structure. Scala case classes are particularly useful for XML serialization.

  2. XML can be created directly using XML literals in Scala, which is a more concise way compared to using a separate XML library.

  3. We use the PrettyPrinter class to format our XML output in a more readable way.

  4. For parsing XML, we use XML.loadString method, which is similar to the Unmarshal function in the Go example.

  5. To create nested XML structures, we can use XML literals and embed Scala code within curly braces {} to generate dynamic content.

  6. Scala’s pattern matching and functional programming features make it easy to extract data from XML structures.

Note that Scala’s XML handling is more integrated into the language compared to Go’s approach, allowing for more concise and idiomatic code when working with XML.

To run this program, save it as XMLExample.scala and use the scala command:

$ scala XMLExample.scala

This will output the XML representations and the parsed Plant object, similar to the Go example.