3

I'm trying to generate a java classes from multiple xsd files. But I get this error.

org.xml.sax.SAXParseException; ... 'somelement' is already defined

I think it's due to the common types that included multiple times.

How can I generate the java classes with maven?

I have the following schemas in a directory:

xsd:

  • EXAMPLE_QualifyRS.xsd
  • EXAMPLE_QualifyRQ.xsd
  • EXAMPLE_Peble_CommonTypes.xsd
  • EXAMPLE_CommonTypes.xsd
  • EXAMPLE_SimpleTypes.xsd

EXAMPLE_QualifyRS.xsd

<xs:schema xmlns="http://www.example.org/EXAMPLE/2007/00" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/EXAMPLE/2007/00" elementFormDefault="qualified" version="1.002" id="EXAMPLE2016.1">
    <xs:include schemaLocation="EXAMPLE_CommonTypes.xsd"/>
    <xs:include schemaLocation="EXAMPLE_SimpleTypes.xsd"/>
    <xs:include schemaLocation="EXAMPLE_Peble_CommonTypes.xsd"/>
         <xs:element name="someelement">...</xs:element>

EXAMPLE_Peble_CommonTypes.xsd

<xs:schema xmlns="http://www.example.org/EXAMPLE/2007/00" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/EXAMPLE/2007/00" elementFormDefault="qualified" version="1.000" id="EXAMPLE2016.1">
    <xs:include schemaLocation="EXAMPLE_CommonTypes.xsd"/>

EXAMPLE_QualifyRQ.xsd

<xs:schema xmlns="http://www.example.org/EXAMPLE/2007/00" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/EXAMPLE/2007/00" elementFormDefault="qualified" version="1.001" id="EXAMPLE2016.1">
    <xs:include schemaLocation="EXAMPLE_CommonTypes.xsd"/>
    <xs:include schemaLocation="EXAMPLE_SimpleTypes.xsd"/>
    <xs:include schemaLocation="EXAMPLE_Peble_CommonTypes.xsd"/>
        <xs:element name="someelement">...</xs:element>

And here is how I generate my class in maven

<plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>jaxb2-maven-plugin</artifactId>
                <version>2.4</version>
                <executions>
                    <execution>
                        <id>example-schema</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>xjc</goal>
                        </goals>
                        <configuration>
                            <xsdPathWithinArtifact>xsd</xsdPathWithinArtifact>
                            <addGeneratedAnnotation>true</addGeneratedAnnotation>
                            <laxSchemaValidation>true</laxSchemaValidation>
                            <laxSchemaValidation>true</laxSchemaValidation>
                            <readOnly>true</readOnly>
                            <verbose>true</verbose>
                            <sources>
                                <source>src/main/resources/xsd</source>
                            </sources>
                            <packageName>com.example</packageName>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
user311633
  • 173
  • 3
  • 11

1 Answers1

4

Let's say you have a "Person" in your common.xsd, as example below:

<xs:schema xmlns="common.schema.def"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="common.schema.def"
           elementFormDefault="qualified">

    <xs:complexType name="Person">
        <xs:sequence>
                <xs:element name="name" type="xs:string"/>
                <xs:element name="age" type="xs:int"/>
        </xs:sequence>
    </xs:complexType>
</xs:schema>

And you want to use it in another schema. Then you would do:

<xs:schema xmlns="http://www.example.org/EXAMPLE/2007/00"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:common="common.schema.def"
           targetNamespace="http://www.example.org/EXAMPLE/2007/00"
           elementFormDefault="qualified">
    <xs:import namespace="common.schema.def" schemaLocation="common.xsd"/>

    <xs:complexType name="someClass">
        <xs:sequence>
            <xs:element name="person" type="common:Person"/>
            <xs:element name="alias" type="xs:string"/>
        </xs:sequence>
    </xs:complexType>
</xs:schema>

Edit to reply on the comment:

The name collision happens because you specify package name in the plugin. Then classes with the same name are attempted to be placed under the same package. Let's remove the package naming from the plugin and use bindings to create the desired package per schema.

Your plugin would look like this:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>jaxb2-maven-plugin</artifactId>
    <version>2.4</version>
    <executions>
        <execution>
            <id>example-schema</id>
            <phase>generate-sources</phase>
            <goals>
                <goal>xjc</goal>
            </goals>
            <configuration>
                <xsdPathWithinArtifact>xsd</xsdPathWithinArtifact>
                <addGeneratedAnnotation>true</addGeneratedAnnotation>
                <laxSchemaValidation>true</laxSchemaValidation>
                <laxSchemaValidation>true</laxSchemaValidation>
                <readOnly>true</readOnly>
                <verbose>true</verbose>
                <sources>
                    <source>src/main/resources/xsd</source>
                </sources>
                <xjbSources>
                    <xjbSource>src/main/resources/xjb</xjbSource>
                </xjbSources>
            </configuration>
        </execution>
    </executions>
</plugin>

And the bindings.xjb would look like this:

<jxb:bindings version="1.0"
              xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
              xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <jxb:bindings schemaLocation="../xsd/common.xsd">
        <jxb:schemaBindings>
            <jxb:package name="common.packagename"/>
        </jxb:schemaBindings>
    </jxb:bindings>
    <jxb:bindings schemaLocation="../xsd/someothercommon.xsd">
        <jxb:schemaBindings>
            <jxb:package name="othercommon.packagename"/>
        </jxb:schemaBindings>
    </jxb:bindings>
</jxb:bindings>

To test it I used another xsd with an element named Person that looks like this:

<xs:schema xmlns="othercommon.schema.def"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="othercommon.schema.def"
           elementFormDefault="qualified">

    <xs:complexType name="Person">
        <xs:sequence>
            <xs:element name="alias" type="xs:string"/>
            <xs:element name="id" type="xs:int"/>
        </xs:sequence>
    </xs:complexType>
</xs:schema>

And the schema that uses both is updated to this:

<xs:schema xmlns="http://www.example.org/EXAMPLE/2007/00"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:common="common.schema.def"
           xmlns:othercommon="othercommon.schema.def"
           targetNamespace="http://www.example.org/EXAMPLE/2007/00"
           elementFormDefault="qualified">
    <xs:import namespace="common.schema.def" schemaLocation="common.xsd"/>
    <xs:import namespace="othercommon.schema.def" schemaLocation="someothercommon.xsd"/>

    <xs:complexType name="someClass">
        <xs:sequence>
            <xs:element name="person" type="common:Person"/>
            <xs:element name="otherpersontype" type="othercommon:Person"/>
        </xs:sequence>
    </xs:complexType>
</xs:schema>
martidis
  • 2,897
  • 1
  • 11
  • 13
  • Unfortunately, I'm unable to change the schema. As this schema is from another international organisation. Is there a way to generate java classes from these schema? – user311633 Oct 24 '18 at 10:22
  • @user311633 is it the same element name for different elements? – martidis Oct 24 '18 at 10:25
  • That's right, it is the same element name for different elements in a different schema. I don't mind to use other plugins too if I have to. – user311633 Oct 24 '18 at 21:14
  • @user311633 edited answer to solve your name collision problem – martidis Oct 25 '18 at 07:39