Search code examples
javaxmlxsdjaxbupnp

Is this offical Xml schema invalid or is error limitation of Jaxb


uPnP defines a number of Xml schemas including didl-lite.xsd, including this section:

<xsd:sequence>
  <xsd:element ref="dc:title"/>
  <xsd:group ref="didl-lite:allowed-under-container" minOccurs="0" maxOccurs="unbounded"/>
  <xsd:group ref="upnp:class.group"/>
  <xsd:group ref="didl-lite:allowed-under-container" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>

When I tried to build Java classes from this using jaxb it complained

Removing the second xsd:group ref="didl-lite:allowed-under-container" minOccurs="0" maxOccurs="unbounded" line so we have

<xsd:sequence>
  <xsd:element ref="dc:title"/>
  <xsd:group ref="didl-lite:allowed-under-container" minOccurs="0" maxOccurs="unbounded"/>
  <xsd:group ref="upnp:class.group"/>
</xsd:sequence>

fixed the issue, and seems to make more sense.

But I am not clear is the Xsd actually invalid or is this just a limitation of generating Jaxb classes from Xsd?


Solution

  • I think both semantically and formally the schema provided is valid.

    You can, for instance, verify the schema well-formedness with Java or online, for example, in this site.

    The issue you are facing could be considered a kind of limitation of JAXB.

    The limitation consists in that the generator encounters a value that has been already taken into consideration in the process of generating your classes, and it has a problem, because it will be unable to generate a property and the corresponding related methods and stuff for this second value because the names are already taken.

    I will use the xjc tool for code generation but the solution should be portable to the Maven or Gradle plugins too.

    If you run the xjc tool like this:

    xjc -d out didl-lite-v2.xsd
    

    the error description will give you a possible solution:

    [ERROR] Property "AllowedUnderItem" is already defined. Use <jaxb:property> to resolve this conflict
    

    The mentioned term <jaxb:property> has to do with JAXB XML bindings.

    JAXB XML bindings allows you to customize the JAXB Java classes generation process in different ways.

    The necessary configuration is provided in a XML file with a certain information.

    In this specific use case, you can define the following bindings XML file, let's name it binding.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <jaxb:bindings 
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
        version="2.1">
    
        <jaxb:bindings schemaLocation="didl-lite-v2.xsd">
            <jaxb:bindings
                node="//xsd:complexType[@name='container.type']/xsd:sequence/xsd:group[@ref='didl-lite:allowed-under-container'][2]">
                <jaxb:property name="allowedUnderContainerAfterUpnpClassGroup"/>
            </jaxb:bindings>
            <jaxb:bindings
                node="//xsd:complexType[@name='item.type']/xsd:sequence/xsd:group[@ref='didl-lite:allowed-under-item'][2]">
                <jaxb:property name="allowedUnderItemAfterUpnpClassGroup"/>
            </jaxb:bindings>
        </jaxb:bindings>
    </jaxb:bindings>
    

    As you can see, we are indicating that the second occurrence of the allowed-under-item group, represented by the XPath expression //xsd:complexType[@name='item.type']/xsd:sequence/xsd:group[@ref='didl-lite:allowed-under-item'][2], should be treated as allowedUnderItemAfterUpnpClassGroup. We need to do something similar with allowed-under-container.

    Then, if you run again the xjc tool passing in this XML bindings file, your classes will be generated successfully:

    xjc -d out -b binding.xml didl-lite-v2.xsd
    

    This or this other SO questions could be of help as well.