问题
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