Home > Blockchain >  How do I "import" an xml schema for xjb code generation
How do I "import" an xml schema for xjb code generation

Time:07-24

I'm new to using xml, and having trouble figuring this out. I found a schema for the RSS spec online, and I can generate java classes from that self-contained schema using xjc without issues.

I want to add fields from simpledc.xsd because in RSS feeds, I'm seeing tags like dc:creator on <items>, and I'd like to set it up so code generation for that can work too. In my attempt, I added the xsd:include for the dc schema, and added a field to the item definition.

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <!-- My addition -->
    <xsd:include schemaLocation="simpledc.xsd" />

    <xsd:element name="rss" type="rss" />

    <xsd:complexType name="rss">
        <xsd:sequence>
            <xsd:element name="channel" type="channel" maxOccurs="1"
                minOccurs="1" />
...

    <xsd:complexType name="item">
        <xsd:sequence>
            <xsd:element name="title" type="xsd:string" maxOccurs="1" minOccurs="0">
                <xsd:annotation>
                    <xsd:documentation>
                        The title of the item.
                    </xsd:documentation>
                </xsd:annotation>
            </xsd:element>
            ...
            <!-- My addition -->
            <xsd:element name="creator" type="dc:creator" maxOccurs="1" minOccurs="0" />
        </xsd:sequence>
    </xsd:complexType>

Intellij provides the error:

Cannot resolve symbol 'dc:creator'

And xjc also provides a similar error:

$ xjc -p com.test.generated -d src/main/java/ src/main/resources/schemas/rss.xsd
parsing a schema...
[ERROR] s4s-att-invalid-value: Invalid attribute value for 'type' in element 'element'. Recorded reason: UndeclaredPrefix: Cannot resolve 'dc:creator' as a QName: the prefix 'dc' is not declared.
  line 391 of file:/<project>/src/main/resources/schemas/rss.xsd

How do I set this up properly so that I can add elements with the dc namespace in my xml schema, and have codegen work properly?

CodePudding user response:

Customizations to the default JAXB bindings are made in the form of binding declarations passed to the JAXB binding compiler, and can be made in two ways:

  1. As inline annotations in a source XML schema
  2. As declarations in an external binding customizations file

Inline Customizations

Customizations to JAXB bindings made by means of inline binding declarations in an XML schema file take the form of <xsd:appinfo> elements embedded in schema <xsd:annotation> elements (xsd: is the XML schema namespace prefix). The general form for inline customizations is:

<xs:annotation>
   <xs:appinfo>
      .
      .
      binding declarations
      .
      .
   </xs:appinfo>
</xs:annotation> 

Customizations are applied at the location at which they are declared in the schema. For example, a declaration at the level of a particular element would apply to that element only. Note that the XMLSchema namespace prefix must be used with the <annotation> and <appinfo> declaration tags. In the example above, xs: is used as the namespace prefix, so the declarations are tagged <xs:annotation> and <xs:appinfo>.

External Binding Customization Files

Customizations to JAXB bindings made by means of an external file containing binding declarations take the general form:

<jxb:bindings schemaLocation = "xs:anyURI">
   <jxb:bindings node = "xs:string">*
      <binding declaration>
   <jxb:bindings>
</jxb:bindings> 
  • schemaLocation is a URI reference to the remote schema
  • node is an XPath 1.0 expression that identifies the schema node within schemaLocation to which the given binding declaration is associated.

For example, the first schemaLocation/node declaration in a JAXB binding declarations file specifies the schema name and the root schema node:

<jxb:bindings schemaLocation="po.xsd" node="/xs:schema"> 

A subsequent schemaLocation/node declaration, say for a simpleType element named ZipCodeType in the above schema, would take the form:

<jxb:bindings node="//xs:simpleType[@name='ZipCodeType']"> 

See the docs for more detail.

CodePudding user response:

I figured out how to do this. I used an include where I should have used an import because I was referencing a different namespace. And then for the element from the different namespace, I need to use a ref to link to them:

<xsd:schema 
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:dc="http://purl.org/dc/elements/1.1/">
    <xsd:import schemaLocation="dc.xsd" namespace="http://purl.org/dc/elements/1.1/"/>
...
    <xsd:complexType name="item">
        <xsd:sequence>
            ...
            <!-- My addition -->
            <xsd:element minOccurs="0" ref="dc:creator" />
        </xsd:sequence>
    </xsd:complexType>

I'm not sure what the intent of the simpledc.xsd provided by the dublin core website. Using dc.xsd seems to work for generating the schema.

Unfortunately, when you're trying to unmarshall xml according to this schema, it seems that the rss feed author needs to add xmlns fields at the top level <rss> element, and they mostly do not.

  • Related