scalaxb

scalaxb is an XML data-binding tool for Scala that supports W3C XML Schema (xsd) as the input file.

try it online

  • schema file add
  • schema URL add
  • default package
  • namespace URI package add

usage

$ scalaxb [options] <schema_file>...
  -d <directory> | --outdir <directory>
        generated files will go into <directory>
  -p <package> | --package <package>
        specifies the target package
  -p:<namespaceURI>=<package> | --package:<namespaceURI>=<package>
        specifies the target package for <namespaceURI>
  -v | --verbose
        be extra verbose
  <schema_file>...
        input schema to be converted

status

This is still at pre-ALPHA state, and many things don't work. I'd really appreciate if you could run it against your favorite xsd file and let me know the result.

installation

You can install it using sbaz:

  $ sudo sbaz install scalaxb

or build from the source:

  $ git clone git://github.com/eed3si9n/scalaxb.git scalaxb
  $ cd scalaxb
  $ sbt sbaz

See INSTALL for details.

example

Suppose you have address.xsd:

<xs:schema targetNamespace="http://www.example.com/IPO"
        xmlns="http://www.example.com/IPO"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns:ipo="http://www.example.com/IPO">
  <xs:complexType name="Address">
    <xs:sequence>
      <xs:element name="name"   type="xs:string"/>
      <xs:element name="street" type="xs:string"/>
      <xs:element name="city"   type="xs:string"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="USAddress">
    <xs:complexContent>
      <xs:extension base="ipo:Address">
        <xs:sequence>
          <xs:element name="state" type="xs:string"/>
          <xs:element name="zip"   type="xs:positiveInteger"/>
        </xs:sequence>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>
</xs:schema>

You then run the following:

$ scalaxb address.xsd

You get address.scala that contains case classes that can parse XML
documents conforming to the address.xsd:

// Generated by <a href="http://scalaxb.org/">scalaxb</a>.
import org.scalaxb.rt
 
case class Address(name: String,
  street: String,
  city: String) extends Addressable
 
object Address extends rt.ElemNameParser[Address] {
  val targetNamespace = "http://www.example.com/IPO"
 
  def parser(node: scala.xml.Node): Parser[Address] =
    (rt.ElemName(targetNamespace, "name")) ~ 
      (rt.ElemName(targetNamespace, "street")) ~ 
      (rt.ElemName(targetNamespace, "city")) ^^
        { case p1 ~ 
      p2 ~ 
      p3 => Address(p1.text,
      p2.text,
      p3.text) }
 
  def toXML(__obj: Address, __namespace: String, __elementLabel: String): scala.xml.NodeSeq = {
    var __scope: scala.xml.NamespaceBinding = scala.xml.TopScope
    __scope = scala.xml.NamespaceBinding("xsi", "http://www.w3.org/2001/XMLSchema-instance", __scope)
    __scope = scala.xml.NamespaceBinding("ipo", "http://www.example.com/IPO", __scope)
    __scope = scala.xml.NamespaceBinding("xs", "http://www.w3.org/2001/XMLSchema", __scope)
    __scope = scala.xml.NamespaceBinding(null, "http://www.example.com/IPO", __scope)
    val node = toXML(__obj, __namespace, __elementLabel, __scope)
    node match {
      case elem: scala.xml.Elem =>
        elem % new scala.xml.PrefixedAttribute(__scope.getPrefix(rt.Helper.XSI_URL),
          "type",
          "ipo:Address", elem.attributes)
      case _ => node
    }
  }
 
  def toXML(__obj: Address, __namespace: String, __elementLabel: String, __scope: scala.xml.NamespaceBinding): scala.xml.NodeSeq = {
    val prefix = __scope.getPrefix(__namespace)
    var attribute: scala.xml.MetaData  = scala.xml.Null
 
    scala.xml.Elem(prefix, __elementLabel,
      attribute, __scope,
      Seq.concat(scala.xml.Elem(prefix, "name", scala.xml.Null, __scope, scala.xml.Text(__obj.name.toString)),
        scala.xml.Elem(prefix, "street", scala.xml.Null, __scope, scala.xml.Text(__obj.street.toString)),
        scala.xml.Elem(prefix, "city", scala.xml.Null, __scope, scala.xml.Text(__obj.city.toString))): _*)
  }
 
 
}
 
 
 
trait Addressable {
  val name: String
  val street: String
  val city: String
}
 
object Addressable extends rt.ImplicitXMLWriter[Addressable] {
  def fromXML(seq: scala.xml.NodeSeq): Addressable = seq match {
    case node: scala.xml.Node =>     
      val typeName = (node \ "@{http://www.w3.org/2001/XMLSchema-instance}type").text    
      val namespace = if (typeName.contains(':'))
        node.scope.getURI(typeName.dropRight(typeName.length - typeName.indexOf(':')))
      else node.scope.getURI(null)
 
      val value = if (typeName.contains(':')) typeName.drop(typeName.indexOf(':') + 1)
      else typeName
 
      (namespace, value) match {
        case ("http://www.example.com/IPO", "USAddress") => USAddress.fromXML(node)
        case _ => Address.fromXML(node)
      }
    case _ => error("fromXML failed: seq must be scala.xml.Node")
  }
 
  def toXML(__obj: Addressable, __namespace: String, __elementLabel: String,
      __scope: scala.xml.NamespaceBinding): scala.xml.NodeSeq = __obj match {
    case x: USAddress => USAddress.toXML(x, __namespace, __elementLabel, __scope)
    case x: Address => Address.toXML(x, __namespace, __elementLabel, __scope)
  }
}
 
 
 
case class USAddress(name: String,
  street: String,
  city: String,
  state: String,
  zip: Int) extends Addressable
 
object USAddress extends rt.ElemNameParser[USAddress] {
  val targetNamespace = "http://www.example.com/IPO"
 
  def parser(node: scala.xml.Node): Parser[USAddress] =
    (rt.ElemName(targetNamespace, "name")) ~ 
      (rt.ElemName(targetNamespace, "street")) ~ 
      (rt.ElemName(targetNamespace, "city")) ~ 
      (rt.ElemName(targetNamespace, "state")) ~ 
      (rt.ElemName(targetNamespace, "zip")) ^^
        { case p1 ~ 
      p2 ~ 
      p3 ~ 
      p4 ~ 
      p5 => USAddress(p1.text,
      p2.text,
      p3.text,
      p4.text,
      p5.text.toInt) }
 
  def toXML(__obj: USAddress, __namespace: String, __elementLabel: String): scala.xml.NodeSeq = {
    var __scope: scala.xml.NamespaceBinding = scala.xml.TopScope
    __scope = scala.xml.NamespaceBinding("xsi", "http://www.w3.org/2001/XMLSchema-instance", __scope)
    __scope = scala.xml.NamespaceBinding("ipo", "http://www.example.com/IPO", __scope)
    __scope = scala.xml.NamespaceBinding("xs", "http://www.w3.org/2001/XMLSchema", __scope)
    __scope = scala.xml.NamespaceBinding(null, "http://www.example.com/IPO", __scope)
    val node = toXML(__obj, __namespace, __elementLabel, __scope)
    node match {
      case elem: scala.xml.Elem =>
        elem % new scala.xml.PrefixedAttribute(__scope.getPrefix(rt.Helper.XSI_URL),
          "type",
          "ipo:USAddress", elem.attributes)
      case _ => node
    }
  }
 
  def toXML(__obj: USAddress, __namespace: String, __elementLabel: String, __scope: scala.xml.NamespaceBinding): scala.xml.NodeSeq = {
    val prefix = __scope.getPrefix(__namespace)
    var attribute: scala.xml.MetaData  = scala.xml.Null
 
    scala.xml.Elem(prefix, __elementLabel,
      attribute, __scope,
      Seq.concat(scala.xml.Elem(prefix, "name", scala.xml.Null, __scope, scala.xml.Text(__obj.name.toString)),
        scala.xml.Elem(prefix, "street", scala.xml.Null, __scope, scala.xml.Text(__obj.street.toString)),
        scala.xml.Elem(prefix, "city", scala.xml.Null, __scope, scala.xml.Text(__obj.city.toString)),
        scala.xml.Elem(prefix, "state", scala.xml.Null, __scope, scala.xml.Text(__obj.state.toString)),
        scala.xml.Elem(prefix, "zip", scala.xml.Null, __scope, scala.xml.Text(__obj.zip.toString))): _*)
  }
 
 
}