Let's assume we defined a collection type in XSD as
<xs:complexType name="Foos">
<xs:sequence>
<xs:element name="foo" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:all>
<xs:element name="bar" type="xs:string"/>
<xs:element name="baz" type="xs:string"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
When generating Java code from it using XJC the type roughly translates to
public class Foos {
public List<Foos.Foo> getFoos();
public static class Foo {
public String getBar();
public String getBaz();
}
}
As the collection type is part of some other type such as the root of the document, client code of the generated code looks somewhat like this
for(Foo foo : document.getFoos().getFoos())
{
//do something
}
Is there any way to make the client code less ugly without writing a wrapper manually?
It should look like this
for(Foo foo : document.getFoos())
{
//do something
}
Thanks
There are XJC plug-ins that people have written to generate the @XmlElementWrapper
annotation instead of having the extra wrapper class.
Alternative you could create the class with the @XmlElementWrapper
yourself and have the generated classes reference it by doing the following:
Document
You could handcraft your own Document
class to get the desired behaviour. You can get the behaviour you are looking for by leveraging the @XmlElementWrapper
annotation to get a grouping element.
package forum18247182;
import java.util.*;
import javax.xml.bind.annotation.*;
public class Document {
private List<Foos.Foo> foos = new ArrayList<Foos.Foo>();
@XmlElementWrapper
@XmlElement(name="foo")
public List<Foos.Foo> getFoos() {
return foos;
}
}
XML Schema (schema.xsd)
Here is an expanded XML schema based on your fragment that I will use.
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/schema"
xmlns="http://www.example.org/schema"
elementFormDefault="qualified">
<xs:element name="document" type="Document"/>
<xs:complexType name="Document">
<xs:sequence>
<xs:element name="foos" type="Foos"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Foos">
<xs:sequence>
<xs:element name="foo" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:all>
<xs:element name="bar" type="xs:string" />
<xs:element name="baz" type="xs:string" />
</xs:all>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>
Leverage Existing Class When Generating Java Model from XML Schema (binding.xml)
We will use an external binding file to indicate that during class generation we wish to use our existing class for the complex type called Document
.
<jxb:bindings
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
version="2.1">
<jxb:bindings schemaLocation="schema.xsd">
<jxb:bindings node="//xs:complexType[@name='Document']">
<jxb:class ref="forum18247182.Document"/>
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
XJC Call
We will use the -b
option to specify our binding file. We will also use the -p
option to force the package name of the generated classes to match that of our Document
class. We could also have made the package name of our Document
class match the package name that results from generating classes from the XML schema.
xjc -b binding.xml -p forum18247182 schema.xsd
Demo Code
package forum18247182;
import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;
import forum18247182.Foos.Foo;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance("forum18247182");
Unmarshaller unmarshaller = jc.createUnmarshaller();
StreamSource xml = new StreamSource("src/forum18247182/input.xml");
Document document = unmarshaller.unmarshal(xml, Document.class).getValue();
for(Foo foo : document.getFoos())
{
System.out.println(foo);
}
}
}
Output
Below is the output from running the demo code:
forum18247182.Foos$Foo@51f3336e
forum18247182.Foos$Foo@35b5a4ca
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With