So we have an XSD type in the form:
<xs:complexType name="Foo">
<xs:all>
<xs:element name="Bars">
<xs:complexType>
<xs:sequence>
<xs:element name="Bar" type="barType" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:all>
</xs:complexType>
to represent XML:
<Foo>
<!-- Elements snipped for brevity-->
<Bars>
<Bar>
<!-- Bar Element -->
</Bar>
</Bars>
</Foo>
xjc produces almost correct results. The only annoying thing is that "Bars" is created as an inner class which stores a list of Bars. Is there anyway to have Bars be a List in Foo while still retaining the XML above?
Another way would be to drop the surrounding <bars> element, the XML does not look so nice anymore, but it would make the java code easier to read. Together with xjc's simple binding (see http://jaxb.java.net/nonav/jaxb20-fcs/docs/vendorCustomizations.html) it will produce quite pretty and usefull java code.
When you define Bars as a complex type, Bars will be generated as separated class. Like this I find schema also easier to read. Bars will not be List in Foo unless you change maxOccurs to a value higher than 1 - you cannot do this on xs:all but you can use xs:sequence.
...
<xs:complexType name="Foo">
<xs:all>
<xs:element name="Bars" type="Bars" />
</xs:all>
</xs:complexType>
<xs:complexType name="Bars">
<xs:sequence>
<xs:element name="Bar" type="barType" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
...
After running xjc:
Foo.java:
...
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Foo", propOrder = {
})
public class Foo {
@XmlElement(name = "Bars", required = true)
protected Bars bars;
public Bars getBars() {
return bars;
}
public void setBars(Bars value) {
this.bars = value;
}
}
Bars.java:
...
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Bars", propOrder = {
"bar"
})
public class Bars {
@XmlElement(name = "Bar", required = true)
protected List<String> bar;
...
}
With xs:seqence to get the list of Bars (maxOccurs="unbounded"):
XSD:
...
<xs:complexType name="Foo">
<xs:sequence>
<xs:element name="Bars" type="Bars" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="Bars">
<xs:sequence>
<xs:element name="Bar" type="barType" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
...
Foo.java:
...
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Foo", propOrder = {
"bars"
})
public class Foo {
@XmlElement(name = "Bars", required = true)
protected List<Bars> bars;
public List<Bars> getBars() {
if (bars == null) {
bars = new ArrayList<Bars>();
}
return this.bars;
}
}
Bjarne Hansen's plugin for xjc (https://github.com/dmak/jaxb-xew-plugin) would allow you to stay with "Bars" enclosing element, generating convenient @XmlElementWrapper(name="Bars") annotation.
Maybe below sample helps.
XML Schema
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="test">
<xs:sequence>
<xs:element name="dataList" type="xs:string" nillable="true" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="str" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
Java class :
public class Test {
protected List<String> dataList;
protected String str;
public List<String> getDataList() {
if (dataList == null) {
dataList = new ArrayList<String>();
}
return this.dataList;
}
public String getStr() {
return str;
}
public void setStr(String value) {
this.str = value;
}
}
EDIT 1:
You can reverse engineer from java code to xsd.
in JAVA_HOME/bin there is schemagen executable.
Give your java code and it will create the XSD schema for you using your java class.
see this link
schemagen myObj1.java myObj2.java
You could do the following:
package example;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name="Foo")
public class Foo {
private List<Bar> bar;
public List<Bar> getBar() {
return bar;
}
@XmlElementWrapper(name="Bars")
@XmlElement(name="Bar")
public void setBar(List<Bar> bar) {
this.bar = bar;
}
}
and
package example;
public class Bar {
}
Then you can process your XML using the following code;
package example;
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Foo.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
Foo foo = (Foo) unmarshaller.unmarshal(new File("src/forum128/input.xml"));
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(foo, System.out);
}
}