eed3si9n / scalaxb

scalaxb is an XML data binding tool for Scala.

Home Page:http://scalaxb.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Parsing of element with substitutionGroup fails

ArminWiebigke opened this issue · comments

Steps

Given a XSD with an abstract type, for which concrete elements are provided via substitutionGroup:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:complexType name="AnimalType" abstract="true">
        <xs:sequence>
            <xs:element name="species" type="xs:string"/>
        </xs:sequence>
    </xs:complexType>
    <xs:element name="Animal" type="AnimalType" abstract="true"/>
    <xs:element name="Dog" substitutionGroup="Animal">
        <xs:complexType>
            <xs:complexContent>
                <xs:extension base="AnimalType">
                    <xs:sequence>
                        <xs:element name="furColor" type="xs:string"/>
                    </xs:sequence>
                </xs:extension>
            </xs:complexContent>
        </xs:complexType>
    </xs:element>
    <xs:element name="Fish" substitutionGroup="Animal">
        <xs:complexType>
            <xs:complexContent>
                <xs:extension base="AnimalType">
                    <xs:sequence>
                        <xs:element name="scalesColor" type="xs:string"/>
                    </xs:sequence>
                </xs:extension>
            </xs:complexContent>
        </xs:complexType>
    </xs:element>
    <xs:complexType name="PetType">
        <xs:sequence>
            <xs:element ref="Animal"/>
        </xs:sequence>
    </xs:complexType>
    <xs:element name="Pet" type="PetType"/>
</xs:schema>

Try to parse a valid XML file for that schema:

<Pet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <Dog>
     <species>dog</species>
     <furColor>brown</furColor>
  </Dog>
</Pet>

Problem

Parsing fails with

scalaxb.ParserFailure: Error while parsing <Pet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <Dog>
        <species>dog</species>
        <furColor>brown</furColor>
      </Dog>
    </Pet>: parser error "'Animal' expected but Dog found" while parsing /Pet/Dog

The generated parser for PetType tries to parse the abstract type directly, instead of the subtypes:

def parser(node: scala.xml.Node, stack: List[scalaxb.ElemName]): Parser[PetType] =
      phrase((scalaxb.ElemName(None, "Animal")) ^^
      { case p1 =>
      PetType(scalaxb.fromXML[AnimalType](p1, scalaxb.ElemName(node) :: stack)) })

Expected

The generated parser/writer should be able to handle all elements that are provided via substitutionGroup for the abstract type.

Notes

I took a look at the code an stumbled upon

 def isSubstitutionGroup(elem: ElemDecl) =
    elem.global && (elem.namespace map { x =>
      context.substituteGroups.contains((elem.namespace, elem.name))
    } getOrElse { false })

Why does this always return false if the namespace is None? Changing it to

elem.global && context.substituteGroups.contains((elem.namespace, elem.name))

results in the parser picking up the concrete types

def parser(node: scala.xml.Node, stack: List[scalaxb.ElemName]): Parser[PetType] =
      phrase((((scalaxb.ElemName(None, "Dog")) ^^ 
      (x => scalaxb.DataRecord(x.namespace, Some(x.name), scalaxb.fromXML[Dog](x, scalaxb.ElemName(node) :: stack)))) | 
      ((scalaxb.ElemName(None, "Fish")) ^^ 
      (x => scalaxb.DataRecord(x.namespace, Some(x.name), scalaxb.fromXML[Fish](x, scalaxb.ElemName(node) :: stack))))) ^^
      { case p1 =>
      PetType(p1) })

but the element loses its type:

case class PetType(Animal: scalaxb.DataRecord[Any])