Abhinav
Abhinav

Reputation: 195

xsd2java generates classes with same names because the xsd has elements with the same name nested within one another

Here is how my xsd looks:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
     elementFormDefault="unqualified"
     attributeFormDefault="unqualified">
    <xs:element name="Root">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="Rooms">
                    <xs:complexType>
                        <xs:sequence maxOccurs="unbounded">
                            <xs:element name="Room">
                                <xs:complexType>
                                    <xs:sequence>
                                        <xs:element name="Metadata">
                                            <xs:complexType>
                                                <xs:sequence>
                                                    <xs:element name="Room">                                
                                                          ...
                                                    </xs:element>
                                                </xs:sequence>
                                            </xs:complexType>
                                        </xs:element>
                                    </xs:sequence>
                                </xs:complexType>
                            </xs:element>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

Here is my xsd2java task config:

task xsd2java {
    def jaxbTargetDir = file("src/main/java")
    def bindingFile = file('src/main/resources/jaxb/bindings.xml')  // Specify the path to your bindings.xml

    doLast {
        jaxbTargetDir.mkdirs()
        ant.taskdef(name: 'xjc', classname: 'com.sun.tools.xjc.XJCTask', classpath: configurations.xsd2java.asPath)
        ant.jaxbTargetDir = jaxbTargetDir
        ant.xjc(destdir: '${jaxbTargetDir}',
                package: 'com.project.schema',
                schema: 'src/main/resources/xsd/sample.xsd',
                binding: bindingFile,
                extension: 'true')
    }
}

compileJava.dependsOn 'xsd2java'

Here is how the generated class looks like:

public class Root {

    public static class Rooms {

        public static class Room {

            public static class Metadata {

                public static class Room { ;

                }
            }
        }
    }
}

You can already see that its creating multiple classes with same name. There is a Room class duplicated and nested inside Metadata which is inside Room. This is throwing an error as Java cannot allow duplicate classnames. So, I have resorted to using binding files to change the inner classname from Room to MetadataRoom.

Here is my binding file:

<jaxb:bindings xmlns:jaxb="https://jakarta.ee/xml/ns/jaxb"
               xmlns:xs="http://www.w3.org/2001/XMLSchema"
               jaxb:version="3.0">
    <jaxb:bindings schemaLocation="../xsd/sample.xsd">
        <jaxb:bindings node="//xs:element[@name='Root']//xs:element[@name='Rooms']//xs:element[@name='Room']//xs:element[@name='Metadata']//xs:element[@name='Room']">
            <jaxb:class name="MetadataRoom"/>
        </jaxb:bindings>
    </jaxb:bindings>
</jaxb:bindings>

When I try to use this, it throws an error that says:

Execution failed for task ':xsd2java'.
> java.lang.IllegalArgumentException: Illegal class inheritance loop.  Outer class MetadataRoom may not subclass from inner class: MetadataRoom

Im not an XSD, or JAXB expert, so I need guidance in this.

I also tried changing the outer Room's classname through the JXB binding, but it throws:

[ant:xjc] [ERROR] XPath evaluation of "//xs:element[@name='Root']//xs:element[@name='Rooms']//xs:element[@name='Room']" results in too many (2) target nodes

Upvotes: 0

Views: 29

Answers (1)

Abhinav
Abhinav

Reputation: 195

https://stackoverflow.com/a/32773096/18054760 this answered my question. Apparently, we should access xs:complexType as that is what JAXB uses to generate classnames not the elements themselves.

Upvotes: 0

Related Questions