Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I generate java classes for xml deserialization using an xml schema?

Tags:

java

jaxb

xsd

I'd like an easy way to generate Java classes from a schema so that I can easily deserialize xml and interpret using the objects.

Using Jaxb would be great, but I'm open to any framework that will accomplish the same thing. The schema is the HL7 CDA Schema. It's very complex and I'm guessing that's why I'm having problems with it.

I tried using xjc and JAXB (this would be ideal) but I get an the following error

xjc -d ~/code/ccd/java -p net.msdelta.cda -xmlschema -verbose CDA.xsd 
parsing a schema...
compiling a schema...
[INFO] generating code
unknown location
Exception in thread "main" java.lang.IllegalArgumentException: trying to create the same field twice: id
    at com.sun.codemodel.internal.JDefinedClass.field(JDefinedClass.java:408)
    at com.sun.codemodel.internal.JDefinedClass.field(JDefinedClass.java:379)
    at com.sun.tools.internal.xjc.generator.bean.field.AbstractFieldWithVar.createField(AbstractFieldWithVar.java:61)
    at com.sun.tools.internal.xjc.generator.bean.field.SingleField.<init>(SingleField.java:78)
    at com.sun.tools.internal.xjc.generator.bean.field.SingleField.<init>(SingleField.java:65)
    at sun.reflect.GeneratedConstructorAccessor8.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at com.sun.tools.internal.xjc.generator.bean.field.GenericFieldRenderer.generate(GenericFieldRenderer.java:53)
    at com.sun.tools.internal.xjc.generator.bean.field.DefaultFieldRenderer.generate(DefaultFieldRenderer.java:68)
    at com.sun.tools.internal.xjc.generator.bean.BeanGenerator.generateFieldDecl(BeanGenerator.java:736)
    at com.sun.tools.internal.xjc.generator.bean.BeanGenerator.generateClassBody(BeanGenerator.java:524)
    at com.sun.tools.internal.xjc.generator.bean.BeanGenerator.<init>(BeanGenerator.java:224)
    at com.sun.tools.internal.xjc.generator.bean.BeanGenerator.generate(BeanGenerator.java:164)
    at com.sun.tools.internal.xjc.model.Model.generateCode(Model.java:275)
    at com.sun.tools.internal.xjc.Driver.run(Driver.java:332)
    at com.sun.tools.internal.xjc.Driver.run(Driver.java:180)
    at com.sun.tools.internal.xjc.Driver._main(Driver.java:105)
    at com.sun.tools.internal.xjc.Driver.access$000(Driver.java:63)
    at com.sun.tools.internal.xjc.Driver$1.run(Driver.java:85)
like image 896
ScArcher2 Avatar asked Aug 30 '11 04:08

ScArcher2


People also ask

Which annotation is needed for serialization and deserialization of XML format in the model classes?

Jackson annotations are useful in defining and controlling the process of serialization and deserialization across various formats such as XML, JSON, and YAML.


2 Answers

If this problem is being caused by a complex type having both an attribute and element with the same name then you can use a JAXB schema bindings file to change the field name corresponding to one of the XML nodes:

        <jxb:bindings node="//xs:attributeGroup[@name='db.common.attributes']/xs:attribute[@name='version']">
            <jxb:property name="commonVersion"/>
        </jxb:bindings>

If the problem is occurring because the element appears multiple times in a sequence (i.e. both inside and outside a choice structure). The you will need to use the following XJC extension:

<jxb:globalBindings>
    <xjc:simple />
</jxb:globalBindings>

For a Complete Example See

  • How do I create JAXB bindings for docbook

Related Links to JAXB and HL7 CDA Schema

  • http://metro.1045641.n5.nabble.com/troubleshoot-quot-trying-to-create-the-same-field-twice-quot-error-td1059643.html
like image 52
bdoughan Avatar answered Nov 19 '22 17:11

bdoughan


Exception Information : java.lang.IllegalArgumentException: trying to create the same field twice.

As the exception says, you are trying to generate code (JAXB) for a Schema having same name for multiple attributes and elements. The simplest work-around is to add a JAXB-Binding file.

Purpose of JAXB-Binding : This file is used to specify alias names for the repeated elements/attributes i.e. if "id" name is repeated, you can specify an alias name as "id1" with the path of that element/attribute.

Sample Binding File :

<jxb:globalBindings>
    <xjc:simple />
</jxb:globalBindings>

<jxb:bindings schemaLocation="Sample.xsd">        
    <!-- ATTRIBUTES -->
    <jxb:bindings node="//xs:element[@name='sample']/xs:complexType/xs:attribute[@name='id']">
        <jxb:property name="id1"/>
    </jxb:bindings>        
    <jxb:bindings node="//xs:element[@name='innersample']/xs:complexType/xs:attribute[@name='id']">
        <jxb:property name="id2"/>
    </jxb:bindings> 

    <!-- ELEMENTS -->                                 
    <jxb:bindings node="//xs:element[@name='sample']/xs:complexType/xs:sequence/xs:element[@name='ID']">
        <jxb:property name="id3"/>
    </jxb:bindings>
    <jxb:bindings node="//xs:element[@name='innersample']/xs:complexType/xs:sequence/xs:element[@name='ID']">
        <jxb:property name="id4"/>
    </jxb:bindings>
</jxb:bindings>

If you are using NETBEANS IDE for JAXB Binding, add the Binding file during creation, and check the "Extension" check box, as XJC is being used.

like image 40
Arun Pratap Avatar answered Nov 19 '22 17:11

Arun Pratap