scalaxb
scalaxb is an XML data-binding tool for Scala that supports W3C XML Schema (xsd) as the input file.
try it online
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 convertedstatus
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))): _*) } }
