Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JAXB XJC compiler disregarding mixed=true on XML Schema documents

Tags:

xml

jaxb

xjc

mixed

XJC seems to be completely ignoring mixed="true" on my XML Schema elements thereby not allowing me to extract text content. From the sample XML below, I need to be able to extract "Title Text." Without mixed="true" being recognized, no accessor is created nor is it unmarshalled from XML:

<?xml version="1.0" encoding="UTF-8"?>
<title xmlns="urn:hl7-org:v3" integrityCheck="true">Title Text</title>

Here's a complete but minimized schema that demonstrates the problem:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xs:schema targetNamespace="urn:hl7-org:v3"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns="urn:hl7-org:v3"
  xmlns:mif="urn:hl7-org:v3/mif"
  elementFormDefault="qualified">

  <xs:complexType name="ST" mixed="true">
  <xs:complexContent>
         <xs:restriction base="ED">
            <xs:sequence>
               <xs:element name="reference" type="xs:string" minOccurs="0" maxOccurs="0"/>
               <xs:element name="thumbnail" type="xs:string" minOccurs="0" maxOccurs="0"/>
            </xs:sequence>
            <xs:attribute name="compression" type="xs:string" use="prohibited"/>
         </xs:restriction>
      </xs:complexContent>
  </xs:complexType>

  <xs:complexType name="ED" mixed="true">
    <xs:complexContent>
      <xs:extension base="BIN">
        <xs:sequence>
          <xs:element name="reference" type="xs:string" minOccurs="0" maxOccurs="1" />
          <xs:element name="thumbnail" minOccurs="0" maxOccurs="1" type="xs:string" />
            </xs:sequence>
        <xs:attribute name="compression" type="xs:string" use="optional" />
        <xs:attribute name="integrityCheck" type="xs:string" use="optional" />
        <xs:attribute name="integrityCheckAlgorithm" type="xs:string" use="optional" default="SHA-1" />
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

  <xs:complexType name="BIN" abstract="true" mixed="true">
    <xs:complexContent>
      <xs:extension base="ANY">
        <xs:attribute name="representation" use="optional" type="xs:string" default="TXT" />
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

  <xs:complexType name="ANY" abstract="true">
    <xs:attribute name="nullFlavor" type="xs:string" use="optional" />
  </xs:complexType>

  <xs:element name="title" type="ST" />
</xs:schema>

Note that in the above I have mixed="true". Despite that, the generated schema fragment doesn't contain a reference to it, nor does the generated class use the XmlMixed annotation, nor a value or contents accessor:

/**
 * <p>Java class for ST complex type.
 * 
 * <p>The following schema fragment specifies the expected content contained within this class.                                                                                                                                              
 * 
 * <pre>
 * <complexType name="ST">
 *   <complexContent>
 *     <restriction base="{urn:hl7-org:v3}ED">
 *       <sequence>
 *         <element name="reference" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="0" minOccurs="0"/>
 *         <element name="thumbnail" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="0" minOccurs="0"/>
 *       </sequence>
 *     </restriction>
 *   </complexContent>
 * </complexType>
 * </pre>
 * 
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "ST")
public class ST
    extends ED
{
}

Why is XJC / JAXB completely disregarding my mixed content fields? I have tried both JAXB 2.1 and JAXB 2.2 but only trivial differences are present in the generated code.

Note: I can't change the schema as the actual schema is a standards-compliant healthcare (HL7) schema.

like image 659
Kaleb Pederson Avatar asked Oct 29 '10 04:10

Kaleb Pederson


People also ask

How do I use JAXB XJC?

Open a command prompt. Run the JAXB schema compiler, xjc command from the directory where the schema file is located. The xjc schema compiler tool is located in the app_server_root \bin\ directory. Use the generated JAXB objects within a Java application to manipulate XML content through the generated JAXB classes.

What is xjc files in JAXB?

Use the Java™ Architecture for XML Binding (JAXB) tools to generate Java classes from an XML schema with the xjc schema compiler tool.

What is JAXB XJC jar?

JAXB Binding Compiler. Contains source code needed for binding customization files into java sources. In other words: the *tool* to generate java classes for the given xml representation. License.


2 Answers

http://blogs.oracle.com/mgrebac/entry/handling_extended_mixed_content_in

This worked! Just create a binding file like so:

<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings
 xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0"
 xmlns:xjc= "http://java.sun.com/xml/ns/jaxb/xjc" jaxb:extensionBindingPrefixes="xjc">
  <jaxb:globalBindings generateMixedExtensions="true"/>
</jaxb:bindings>

Then use the -b parameter on the command line with the way you usually do it.

like image 78
AHungerArtist Avatar answered Oct 13 '22 00:10

AHungerArtist


Years pass by, but this scheme keeps troubling people! I've been struggling with this same XSD (HL7) for the past few days, especially for handling the mixed content element types.

My initial requirment was the opposite of the original poster, as I needed to write simple text inside a mixed element. But I must be able to also read such content, so I applied the same solution suggested in another reply, that is creating a custom binding file and using it in Eclipse's "JAXB Classes from Schema" wizard. In that case you can specifically choose which binding file(s) to use in one of the wizard's dialogs.

As a result, classes are generated with a List<Serializable> content whenever a mixed element type is found. It gets a bit tricky to extract the single piece of information you actually need, but at least you're sure you can programatically access anything that's present in an XML file adhering that XSD.

You can even navigate into more complex mixed contents such as:

<v3:name>
    <v3:given>Sample Given Name</v3:given>
    <v3:family>Sample Family Name</v3:family>
</v3:name>

Where name is defined as such (I removed content not useful for this example from the original XSD):

<xs:complexType name="EN" mixed="true">
    <xs:complexContent>
        <xs:sequence>
            <xs:choice minOccurs="0" maxOccurs="unbounded">
                <xs:element name="delimiter" type="en.delimiter"/>
                <xs:element name="family" type="en.family"/>
                <xs:element name="given" type="en.given"/>
                <xs:element name="prefix" type="en.prefix"/>
                <xs:element name="suffix" type="en.suffix"/>
            </xs:choice>
        </xs:sequence>
    </xs:complexContent>
</xs:complexType>

Types en.family, en.given and such are mixed themselves (and for our purpose we don't need to know anything else).

So, when you access name's content, its List<Serializable> will be composed of:

  1. a String, being the blanks between <v3:name> and <v3:given>
  2. an EnGiven element
  3. a String, being the blanks between </v3:given> and <v3:family>
  4. an EnFamily element
  5. a String, being the blanks between </v3:family> and </v3:name>

EnGiven and EnFamily's content will be each made of a single String, respectively "Sample Given Name" and "Sample Family Name". Again, it is a bit tricky, and you have probably have to put some logic to handle the specific cases, but you can manage it this way.

By the way, populating an element is trivial: just add a String to the desired List<Serializable> content.

like image 43
NikeXTC Avatar answered Oct 13 '22 00:10

NikeXTC