Parser failure in scalaxb.fromXML

217 views
Skip to first unread message

Dave

unread,
Aug 30, 2011, 1:38:00 PM8/30/11
to scalaxb
Hi,
I downloaded the latest version of scalaxb and wanted to create a case
class representation in XML of:

case class Child(name: String, age: Int, birthdate:
Option[java.util.Date])
case class Address(street: String, city: String)
case class Person(name: String, address: Address, children:
List[Child])

I got this far so it looks pretty similar (except for java.util.Date
and List) .
I changed error to sys.error in scalaxb.scala due to deprecation
warnings.

Everything compiles well.
Unfortunately the code generates an error while parsing in .
Am I missing something? Or are case classes as an argument not (yet)
supported?

Thanks,
Dave


Scala 2.9.1.RC4
JDK7 b147
Windows 7 Home Premium 32 bit + SP1
scalaxb 0.6.2


webservice.xsd
==============
<xs:schema targetNamespace="org.scalaxbtest/WS"
elementFormDefault="qualified"
xmlns="org.scalaxbtest/WS"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:ws="org.scalaxbtest/WS">

<xs:complexType name="Child">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="age" type="xs:int"/>
<xs:element name="birthdate" type="xs:date" minOccurs="0"
maxOccurs="1"/>
</xs:sequence>
</xs:complexType>

<xs:simpleType name="ChildList">
<xs:list itemType="ws:Child"/>
</xs:simpleType>

<xs:complexType name="Address">
<xs:sequence>
<xs:element name="street" type="xs:string"/>
<xs:element name="city" type="xs:string"/>
</xs:sequence>
</xs:complexType>

<xs:complexType name="Person">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="address" type="ws:Address"/>
<xs:element name="children" type="ws:ChildList"/>
</xs:sequence>
</xs:complexType>

</xs:schema>

webservice.scala (I leave scalaxb.scala and webservice-
xmlprotocol.scala out)
=========================================================
// Generated by <a href="http://scalaxb.org/">scalaxb</a>.
package ws

case class Child(name: String,
age: Int,
birthdate: Option[javax.xml.datatype.XMLGregorianCalendar])


case class Address(street: String,
city: String)


case class Person(name: String,
address: ws.Address,
children: Seq[ws.Child])



Copy paste for the REPL
=======================
val xmlperson = <person xmlns="org.scalaxbtest/WS">
<name>joe</name><address><street>Bulevard</street>
<city>Helsinki</city></address>
<children><child>
<name>Mary</name>
<age>5</age><birthdate>2004-09-04T18:06:22Z</birthdate>
</child>
<child>
<name>Mazy</name><age>3</age>
</child></children>
</person>

val caseclassperson = scalaxb.fromXML[ws.Person](xmlperson)


Scala REPL session
==================
scala> val xmlperson = <person xmlns="org.scalaxbtest/WS">
| <name>joe</name><address><street>Bulevard</street>
| <city>Helsinki</city></address>
| <children><child>
| <name>Mary</name>
| <age>5</age><birthdate>2004-09-04T18:06:22Z</birthdate>
| </child>
| <child>
| <name>Mazy</name><age>3</age>
| </child></children>
| </person>
xmlperson: scala.xml.Elem =
<person xmlns="org.scalaxbtest/WS">
<name>joe</name><address><street>Bulevard</street>
<city>Helsinki</city></address>
<children><child>
<name>Mary</name>
<age>5</age><birthdate>2004-09-04T18:06:22Z</birthdate>
</child>
<child>
<name>Mazy</name><age>3</age>
</child></children>
</person>

scala> val caseclassperson = scalaxb.fromXML[ws.Person](xmlperson)
scalaxb.ParserFailure: scalaxb.ParserFailure: parser error
"`{org.scalaxbtest/WS
}name' expected but null found" while parsing /{org.scalaxbtest/WS}
person//
^
at scalaxb.package$.fromXML(scalaxb.scala:13)
at ws.XMLProtocol$DefaultWsPersonFormat$$anonfun$parser
$8.apply(webservi
ce_xmlprotocol.scala:71)
at ws.XMLProtocol$DefaultWsPersonFormat$$anonfun$parser
$8.apply(webservi
ce_xmlprotocol.scala:68)
at scala.util.parsing.combinator.Parsers
$Success.map(Parsers.scala:108)
at scala.util.parsing.combinator.Parsers
$Success.map(Parsers.scala:107)
at scala.util.parsing.combinator.Parsers$Parser$$anonfun$map
$1.apply(Par
sers.scala:204)
at scala.util.parsing.combinator.Parsers$Parser$$anonfun$map
$1.apply(Par
sers.scala:204)
at scala.util.parsing.combinator.Parsers$$anon
$3.apply(Parsers.scala:183
)
at scalaxb.ElemNameParser$class.parse(scalaxb.scala:635)
at ws.XMLProtocol$$anon$3.parse(webservice_xmlprotocol.scala:
18)
at scalaxb.ElemNameParser$class.reads(scalaxb.scala:615)
at ws.XMLProtocol$$anon$3.reads(webservice_xmlprotocol.scala:
18)
at scalaxb.package$.fromXML(scalaxb.scala:11)
at .<init>(<console>:8)
at .<clinit>(<console>)
at .<init>(<console>:11)
at .<clinit>(<console>)
at $print(<console>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
java:57)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
sorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at scala.tools.nsc.interpreter.IMain
$ReadEvalPrint.call(IMain.scala:704)

at scala.tools.nsc.interpreter.IMain$Request$$anonfun
$14.apply(IMain.sca
la:920)
at scala.tools.nsc.interpreter.Line$$anonfun$1.apply$mcV
$sp(Line.scala:4
3)
at scala.tools.nsc.io.package$$anon$2.run(package.scala:25)
at java.lang.Thread.run(Thread.java:722)

Also same result when compiled
==============================
test.scala
==========
package test

import scalaxb._
import ws._


object Test extends App {

val xmlperson = <person xmlns="org.scalaxbtest/WS"><name>joe</
name><address><street>Bulevard</street><city>Helsinki</city></
address><children><child><name>Mary</name><age>5</
age><birthdate>2004-09-04T18:06:22Z</birthdate>
</child><child><name>Mazy</name><age>3</age></child></children></
person>

val caseclassperson = scalaxb.fromXML[Person](xmlperson)

}

C:\scala-2.9.1.RC4\examples\scalaxb\webservice>scala test.Test
scalaxb.ParserFailure: scalaxb.ParserFailure: parser error
"`{org.scalaxbtest/WS
}name' expected but null found" while parsing /{org.scalaxbtest/WS}
person//
^
at scalaxb.package$.fromXML(scalaxb.scala:13)
at ws.XMLProtocol$DefaultWsPersonFormat$$anonfun$parser
$8.apply(webservi
ce_xmlprotocol.scala:71)
at ws.XMLProtocol$DefaultWsPersonFormat$$anonfun$parser
$8.apply(webservi
ce_xmlprotocol.scala:68)
at scala.util.parsing.combinator.Parsers
$Success.map(Parsers.scala:108)
at scala.util.parsing.combinator.Parsers
$Success.map(Parsers.scala:107)
etc.

eugene yokota

unread,
Aug 30, 2011, 2:21:52 PM8/30/11
to sca...@googlegroups.com
Hi,

I think the problem is from the schema, specifically the following:

 <xs:simpleType name="ChildList">
       <xs:list itemType="ws:Child"/>
 </xs:simpleType>

A simple type is a type that does not allow child elements or attributes, and is used for things like ints and strings. List derivation allows the user to define things like

<foo>1 2 3</foo>

but not list of a complex type. Instead try the following:

 <xs:complexType name="ChildList">
   <xs:sequence>
     <xs:element name="child" type="Child" minOccurs="0" maxOccurs="unbounded"/>
   </xs:sequence>
 </xs:complexType>

I was able to get the following out of the REPL. (Having REPL reproduction is always helpful, so thanks for that):

scala> scalaxb.fromXML[ws.Person](xmlperson)
res0: ws.Person = Person(joe,Address(Bulevard,Helsinki),ChildList(List(Child(Mary,5,Some(2004-09-04T18:06:22Z)), Child(Mazy,3,None))))

-eugene

Dave

unread,
Aug 30, 2011, 4:23:55 PM8/30/11
to scalaxb
Hi Eugene,
thanks for looking at it.

Is it also possible to get it like

Person(joe,Address(Bulevard,Helsinki),List[Child](Child(Mary,
5,Some(2004­-09-04T18:06:22Z)),
Child(Mazy,3,None)))

thus with List[Child] instead of ChildList(List(...))
Then it saves an extra case class and it looks better.

Greetings,
Dave

eugene yokota

unread,
Aug 30, 2011, 4:39:43 PM8/30/11
to sca...@googlegroups.com
With XML data binding, XML document becomes the main driver of the data structure.
If you don't want the extra case class, you would need to change the schema as follows:

 <xs:complexType name="Person">
   <xs:sequence>
     <xs:element name="name"   type="xs:string"/>
     <xs:element name="address" type="ws:Address"/>
     <xs:element name="child" type="Child" minOccurs="0" maxOccurs="unbounded"/>
   </xs:sequence>
 </xs:complexType>

This generates the following Person:

case class Person(name: String,
  address: ws.Address,
  child: Seq[ws.Child])

and here's the REPL passing in modified xmlperson without <children> tag:

scala> scalaxb.fromXML[ws.Person](xmlperson)res2: ws.Person = Person(joe,Address(Bulevard,Helsinki),List(Child(Mary,5,Some(2004-09-04T18:06:22Z)), Child(Mazy,3,None)))

-eugene

Dave

unread,
Aug 30, 2011, 5:18:04 PM8/30/11
to scalaxb
Hi Eugene,

Thanks again.
Then I leave it with the extra case class, because I want the children
tag in XML too.

Greetings
Dave


My final version is:
webservice.xsd
==============
<xs:schema targetNamespace="org.scalaxbtest/WS"
elementFormDefault="qualified"
xmlns="org.scalaxbtest/WS"
xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:complexType name="Child">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="age" type="xs:int"/>
<xs:element name="birthdate" type="xs:date" minOccurs="0"
maxOccurs="1"/>
</xs:sequence>
</xs:complexType>

<xs:complexType name="Address">
<xs:sequence>
<xs:element name="street" type="xs:string"/>
<xs:element name="city" type="xs:string"/>
</xs:sequence>
</xs:complexType>

<xs:complexType name="Person">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="address" type="Address"/>
<xs:element name="children">
<xs:complexType>
<xs:sequence>
<xs:element name="child" type="Child" minOccurs="0"
maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>

</xs:schema>

which generates:

webservice.scala
================
// Generated by <a href="http://scalaxb.org/">scalaxb</a>.
package ws

case class Child(name: String,
age: Int,
birthdate: Option[javax.xml.datatype.XMLGregorianCalendar])


case class Address(street: String,
city: String)


case class Children(child: ws.Child*)


case class Person(name: String,
address: ws.Address,
children: ws.Children)

test.scala
==========
package test

import scalaxb._
import ws._

object Test extends App {

val xmlperson =
<person xmlns="org.scalaxbtest/WS">
<name>joe</name>
<address>
<street>Bulevard</street>
<city>Helsinki</city>
</address>
<children>
<child>
<name>Mary</name>
<age>5</age>
<birthdate>2004-09-04T18:06:22Z</birthdate>
</child>
<child>
<name>Mazy</name>
<age>3</age>
</child>
</children>
</person>

val caseclassperson = scalaxb.fromXML[Person](xmlperson)
println(caseclassperson)
val xmlperson2 = scalaxb.toXML[Person](caseclassperson, None,
Some("person"), defaultScope)
println(xmlperson2)
}

Output
======


C:\scala-2.9.1.RC4\examples\scalaxb\webservice>scala test.Test
Person(joe,Address(Bulevard,Helsinki),Children(List(Child(Mary,
5,Some(2004-09-04
T18:06:22Z)), Child(Mazy,3,None))))
<person xmlns="org.scalaxbtest/WS" xmlns:xsi="http://www.w3.org/2001/
XMLSchema-i
nstance" xmlns:xs="http://www.w3.org/2001/XMLSchema"><name>joe</
name><address><s
treet>Bulevard</street><city>Helsinki</city></
address><children><child><name>Mar
Reply all
Reply to author
Forward
0 new messages