Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generating Pretty JAXB classes

Tags:

java

xml

jaxb

I have used JAXB for XML parsing in the past and created my own simple classes for it. Those were POJOs like

public class Foo {

    @XmlAttribute
    public String someAttribute;

    public String someElement;

    public Bar bar;
}

Now I want to write a tool that has to parse data from a very complex xml structure and I would like to avoid writing them all by myself. I tried using xjc to generate the classes, but they look entirely different from my example above:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "RulesElementType", propOrder = { "content" })
public class RulesElementType {

    @XmlElementRefs({ @XmlElementRef(name = "flavor2", type = JAXBElement.class, required = false),
            @XmlElementRef(name = "specific", type = JAXBElement.class, required = false),
            @XmlElementRef(name = "category2", type = JAXBElement.class, required = false),
            @XmlElementRef(name = "flavor1", type = JAXBElement.class, required = false),
            @XmlElementRef(name = "print-prereqs", type = JAXBElement.class, required = false),
            @XmlElementRef(name = "prereqs2", type = JAXBElement.class, required = false),
            @XmlElementRef(name = "rules", type = JAXBElement.class, required = false),
            @XmlElementRef(name = "prereqs1", type = JAXBElement.class, required = false) })
    @XmlMixed
    protected List<Serializable> content;
    @XmlAttribute(name = "name")
    protected String name;
    @XmlAttribute(name = "type1")
    protected String type1;
    @XmlAttribute(name = "internal-id")
    protected String internalId;
    @XmlAttribute(name = "source")
    protected String source;
    @XmlAttribute(name = "revision-date")
    protected String revisionDate;

    /* getters and setters omitted */

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "", propOrder = { "value" })
    public static class Category2 {

        @XmlValue
        protected String value;
        @XmlAttribute(name = "name")
        protected String name;

        /* getters and setters omitted */

    }

    /* additional class definitions omitted */

}

To get the element named "flavor1" I have to search the "content" attribute for a JAXBElement named "flavor1" which I find terribly inconvenient. What I would like to be able to do instead is something like:

String flavor1 = rulesElement.getFlavor1();

Is there a way to accomplish this using xjc or another tool?

Edit: The complexType for RulesElementType from my xsd is:

  <xs:complexType name="RulesElementType" mixed="true">
    <xs:choice maxOccurs="unbounded" minOccurs="0">
      <xs:element name="category2">
        <xs:complexType>
          <xs:simpleContent>
            <xs:extension base="xs:string">
              <xs:attribute type="xs:string" name="name" use="optional"/>
            </xs:extension>
          </xs:simpleContent>
        </xs:complexType>
      </xs:element>
      <xs:element name="prereqs2">
        <xs:complexType>
          <xs:simpleContent>
            <xs:extension base="xs:string">
              <xs:attribute type="xs:string" name="name" use="optional"/>
            </xs:extension>
          </xs:simpleContent>
        </xs:complexType>
      </xs:element>
      <xs:element type="xs:string" name="print-prereqs"/>
      <xs:element name="flavor2">
        <xs:complexType mixed="true">
          <xs:choice maxOccurs="unbounded" minOccurs="0">
            <xs:element type="grantType" name="grant"/>
            <xs:element type="stataddType" name="statadd"/>
            <xs:element type="textstringType" name="textstring"/>
            <xs:element type="selectType" name="select"/>
            <xs:element type="replaceType" name="replace"/>
            <xs:element type="modifyType" name="modify"/>
            <xs:element type="dropType" name="drop"/>
            <xs:element type="suggestType" name="suggest"/>
            <xs:element type="stataliasType" name="statalias"/>
          </xs:choice>
          <xs:attribute type="xs:string" name="name" use="optional"/>
        </xs:complexType>
      </xs:element>
      <xs:element type="specificType" name="specific"/>
      <xs:element type="rulesType" name="rules"/>
      <xs:element type="xs:string" name="prereqs1"/>
      <xs:element name="flavor1">
        <xs:complexType mixed="true">
          <xs:choice maxOccurs="unbounded" minOccurs="0">
            <xs:element type="grantType" name="grant"/>
            <xs:element type="stataddType" name="statadd"/>
            <xs:element type="textstringType" name="textstring"/>
            <xs:element type="selectType" name="select"/>
            <xs:element type="replaceType" name="replace"/>
            <xs:element type="modifyType" name="modify"/>
            <xs:element type="dropType" name="drop"/>
            <xs:element type="suggestType" name="suggest"/>
            <xs:element type="stataliasType" name="statalias"/>
          </xs:choice>
          <xs:attribute type="xs:string" name="name" use="optional"/>
        </xs:complexType>
      </xs:element>
    </xs:choice>
    <xs:attribute type="xs:string" name="name" use="optional"/>
    <xs:attribute type="xs:string" name="type1" use="optional"/>
    <xs:attribute type="xs:string" name="internal-id" use="optional"/>
    <xs:attribute type="xs:string" name="source" use="optional"/>
    <xs:attribute type="xs:string" name="revision-date" use="optional"/>
  </xs:complexType>

The XML file looks somewhat similar to this.

I use XMLBeans to generate the xsd. Since the XML file I am reading from has about 680k lines, manually creating the XSD is not an option.

like image 352
jheyd Avatar asked May 01 '26 02:05

jheyd


1 Answers

You can use the Simplify plugin to simplify your content property.

SO disclaimer: I'm the author.

Please see this questions:

Generate java classes from xsd with jaxb from a choice

extracting element text value

In short, if you use this plugin and customize one of the elements which go into your content property with simplify:as-element-property, you can get distinct easy to use element properties per element. I hope this is what you mean with "pretty".

like image 166
lexicore Avatar answered May 03 '26 17:05

lexicore