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

旧街凉风 提交于 2021-01-21 04:26:07

问题


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)

回答1:


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



回答2:


I think you may have hit http://java.net/jira/browse/JAXB-512

JiBX(http://jibx.sourceforge.net/) is another alternative which is better in terms of performance than JAXB. It requires creating a configuration file though - but there are tools available which can generate them automatically for you. More details here ->http://jibx.sourceforge.net/fromschema/index.html




回答3:


Eclipse EMF can generate classes from your xsd scheme, with (de)serialization support. EMF can be used in standalone (non-OSGi) apps too.




回答4:


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.



来源:https://stackoverflow.com/questions/7238643/how-can-i-generate-java-classes-for-xml-deserialization-using-an-xml-schema

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!