Can jaxb generate xml pattern like this? - java

I am expecting a XML generated by JAXB which has the following pattern:
<payload>
<parameters>
<paramName>clientAssocIds</paramName>
<paramVal>0207</paramVal>
<paramName>quoteType</paramName>
<paramVal>NTB</paramVal>
<paramName>quoteDateLimitDays</paramName>
<paramVal>365</paramVal>
<paramName>externalIndicator</paramName>
<paramVal>1</paramVal>
</parameters>
</payload>
The <paramName> and <paramVal> are name and value pairs, which means <paramVal> has to follow <paramName>.
I wrote a XML Schema and use JAXB to generate the java class based on this schema, then I set all the values and marshalled the class, it didn't generate the xml pattern I expected above.
Here is my schema:
<xsd:complexType name="sgrpCommonMessage">
<xsd:sequence>
<xsd:element name="payload" type="payload" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="payload">
<xsd:sequence>
<xsd:choice minOccurs="0" maxOccurs="1">
<xsd:element name="parameters" type="parameter" />
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="parameter">
<xsd:sequence>
<xsd:element minOccurs="0" name="paramName" type="xsd:string" />
<xsd:element minOccurs="0" name="paramVal" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
And the generated xml has a few <parameters>, which is not what I expect. I want to wrap all the <paramName> and <paramVal> pairs in one <parameters>:
<payload>
<parameters>
<paramName>quoteDateLimitDays</paramName>
<paramVal>NTB</paramVal>
</parameters>
<parameters>
<paramName>clientAssocIds</paramName>
<paramVal>0207</paramVal>
</parameters>
<parameters>
<paramName>quoteType</paramName>
<paramVal>NTB</paramVal>
</parameters>
<parameters>
<paramName>externalIndicator</paramName>
<paramVal>NTB</paramVal>
</parameters>
</payload>
I am wondering if JAXB is capable of realizing such XML structure, if not, what API should I use, if yes, how?

You could have an XML schema like the following:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="parameters" type="parameters" />
<xsd:complexType name="parameters">
<xsd:sequence minOccurs="0" maxOccurs="unbounded">
<xsd:element name="paramName" type="xsd:string" />
<xsd:element name="paramValue" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
Then with the generated model you could do:
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance("forum14571803");
ObjectFactory objectFactory = new ObjectFactory();
Parameters parameters = objectFactory.createParameters();
parameters.getParamNameAndParamValue().add(objectFactory.createParametersParamName("A"));
parameters.getParamNameAndParamValue().add(objectFactory.createParametersParamValue("a"));
parameters.getParamNameAndParamValue().add(objectFactory.createParametersParamName("B"));
parameters.getParamNameAndParamValue().add(objectFactory.createParametersParamValue("b"));
JAXBElement<Parameters> root = objectFactory.createParameters(parameters);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
}
Which would give you the following output:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<parameters>
<paramName>A</paramName>
<paramValue>a</paramValue>
<paramName>B</paramName>
<paramValue>b</paramValue>
</parameters>

Related

validate parts of the incoming web service request lazily in JAX-WS RI

I have to process big requests in a Java 8 web service (JAX-WS RI). A request contains a "header" and many "records" like this (not that 2nd, 3rd, 4th, 5th student records are invalid according to the schema):
<helloStudentsServiceRequest>
<workshop>
<name>wsname</name>
<tutor>tutorname</tutor>
</workshop>
<studentList>
<!--1 or more repetitions: -->
<student>
<Name>st1</Name>
<Birth>1999-11-11</Birth>
</student>
<student>
<Name>st2</Name>
</student>
<student>
<Name>st2</Name>
<Birth>199O-11-11</Birth>
</student>
<student>
<Name>st3</Name>
<Birth>stoneage</Birth>
</student>
<student>
<Birth>stoneage</Birth>
</student>
<student>
<Name>st6</Name>
<Birth>2001-11-12</Birth>
</student>
</studentList>
</helloStudentsServiceRequest>
I use a schema (XSD) for describing my interface. For example:
<xsd:complexType name="HelloStudentsServiceRequestType">
<xsd:sequence>
<xsd:element name="workshop" type="WorkshopType" />
<xsd:element name="studentList">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="student" type="StudentType" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="WorkshopType">
<xsd:sequence>
<xsd:element name="name" type="xsd:string" />
<xsd:element name="tutor" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="StudentType">
</xsd:annotation>
<xsd:sequence>
<xsd:element name="Name" type="xsd:string" />
<xsd:element name="Birth" type="xsd:date" />
</xsd:sequence>
</xsd:complexType>
I'd like to use this schema for validating the request.
However I am not allowed to reject a request if a few "record" in it is not valid according to the schema. In that case I have to process the valid records and return some meaningful information (preferably the SAX error) regarding the invalid ones.
I'd like to keep the request's schema free from the technical details neccessary to fullfill this "lazy validation". For example I don't want to use a "big string" to hold the "record" and then validate that string against the schema. That would break the interface and would be difficult to communicate to the clients. So this is no-go for me:
...
<xsd:element name="studentList">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="student" type="xsd:string" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
...
Do you know an elegant way to solve this in JAX-WS RI (JAXB2) ?
It's possible to customize JAXB bindings to map part of the XML to DOM. For details:
https://jaxb.java.net/guide/Avoid_strong_databinding.html#Mapping_to_DOM
So I mapped "WorkshopType" and "StudentType" to DOM. Now it's possible to validate those DOMs individually and reject or partially process the incoming message. It's also possible to catch the SAX exception if a DOM validating is not successful and signal that back to the client.
working example zipped
I used this binding customization:
<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="WorkshopType.xsd"
node="//xsd:complexType[#name='WorkshopType']">
<jxb:dom />
</jxb:bindings>
<jxb:bindings
schemaLocation="StudentType.xsd"
node="//xsd:complexType[#name='StudentType']">
<jxb:dom />
</jxb:bindings>
And these are the schemas:
For the request:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified" xmlns="helloStudentsNS"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0"
targetNamespace="helloStudentsNS">
<xsd:include schemaLocation="StudentType.xsd" />
<xsd:include schemaLocation="WorkshopType.xsd" />
<xsd:element name="helloStudentsServiceRequest" type="HelloStudentsServiceRequestType" />
<xsd:element name="helloStudentsServiceResponse" type="HelloStudentsServiceResponseType" />
<xsd:complexType name="HelloStudentsServiceRequestType">
<xsd:sequence>
<xsd:element name="workshop" type="WorkshopType" />
<xsd:element name="studentList">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="student" type="StudentType" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="HelloStudentsServiceResponseType">
<xsd:sequence>
<xsd:element name="GreetingHeader" type="xsd:string" />
<xsd:element name="StudentGreeting" type="xsd:string" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
For the workshop and student types:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
xmlns="helloStudentsNS"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
jaxb:version="2.0"
targetNamespace="helloStudentsNS">
<xsd:element name="workshop" type="WorkshopType"/>
<xsd:complexType name="WorkshopType">
<!-- <xsd:annotation><xsd:appinfo><jaxb:dom/></xsd:appinfo></xsd:annotation> -->
<xsd:sequence>
<xsd:element name="name" type="xsd:string" />
<xsd:element name="tutor" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
xmlns="helloStudentsNS"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
jaxb:version="2.0" targetNamespace="helloStudentsNS">
<!--
-->
<xsd:element name="student" type="StudentType"/>
<xsd:complexType name="StudentType">
<!-- <xsd:annotation><xsd:appinfo><jaxb:dom/></xsd:appinfo></xsd:annotation> -->
<xsd:sequence>
<xsd:element name="Name" type="xsd:string" />
<xsd:element name="Birth" type="xsd:date" />
</xsd:sequence>
</xsd:complexType>
And this is the java code:
public HelloStudentsServiceResponseType greetStudents(HelloStudentsServiceRequestType req) {
WorkshopType ws;
// unmarshall workshop data
Element element = req.getWorkshop(); // workshop is retrieved as DOM
try {
Unmarshaller u = jc.createUnmarshaller(); // jaxb ri unmarshaller not thread safe: https://jaxb.java.net/guide/Performance_and_thread_safety.html
u.setSchema(workshopSchema); // enable validation by workshopType.xsd
ws = u.unmarshal(element, WorkshopType.class).getValue(); // unmarshal
} catch (JAXBException e) {
// this is fatal
throw new RuntimeException("fatal: invalid workshop data: ", e);
}
// unmarshall students
List<String> studentGreetings = new ArrayList<>();
for(Element studentElement : req.getStudentList().getStudent()) { // retrieve students as DOMs
try {
StudentType st;
Unmarshaller u = jc.createUnmarshaller(); // jaxb ri unmarshaller not thread safe: https://jaxb.java.net/guide/Performance_and_thread_safety.html
u.setSchema(studentSchema); // enable validation by studentType.xsd
st = u.unmarshal(studentElement, StudentType.class).getValue();
studentGreetings.add("Dear " + st.getName() + ", " + st.getBirth() + ", welcome in the workshop!");
} catch (JAXBException e) {
Throwable cause = e.getLinkedException();
if(cause != null) {
studentGreetings.add("Dear student, your data is invalid: " + cause.getMessage());
}
else {
studentGreetings.add("Dear student, there's an unknown problem with your data");
}
}
}
// construct response
HelloStudentsServiceResponseType response = new HelloStudentsServiceResponseType();
response.setGreetingHeader("I'd like to greet everybody in the " + ws.getName() + " workshop. " +
"Your tutor is " + ws.getTutor());
response.getStudentGreeting().addAll(studentGreetings);
return response;
}

XSD declaration of a complex type with repeating attribute outside a list

I have a provider that outputs something like this
<Result rawScore="623">
<Target>http://myUrl.com/test1</Target>
<Domain name="myUrl.search.com" />
<Property name="Language">en</Property>
<Property name="Teaser">This is the description</Property>
<Property name="LVCategory">Help</Property>
<Property name="Title">ProductTitle</Property>
<Property name="Last Modified">2012-04-06T21:44:11Z</Property>
</Result>
I'm trying to create an xsd to leverage jaxb, but I'm not sure how to handle the Property attribute appearing several times but not inside a list, so a sequence won't work. Any ideas?
This is a complete XML Schema, and compiles to Java code
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" version="2.0">
<xsd:element name="Result" type="ResultType"/>
<xsd:complexType name="ResultType">
<xsd:sequence>
<xsd:element name="Target" type="xsd:string"/>
<xsd:element name="Domain" type="xsd:string"/>
<xsd:element name="Property" type="PropertyType"
minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="rawScore" type="xsd:int"/>
<!-- xsd:integer => BigDecimal/PITA -->
</xsd:complexType>
<!-- I prefer explicit types to avoid nested class definitions -->
<xsd:complexType name="PropertyType">
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="name" type="xsd:string"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
</xsd:schema>
A few lines of Java code:
JAXBContext jc = JAXBContext.newInstance( PACKAGE );
Unmarshaller m = jc.createUnmarshaller();
try {
File source = new File( XMLIN );
JAXBElement<ResultType> jbe = (JAXBElement<ResultType>)m.unmarshal( source );
ResultType result = (ResultType)jbe.getValue();
} catch( Exception e ){
}
You could do something like the following:
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema">
<element name="Result">
<complexType>
<sequence>
...
<element name="Property" minOccurs="0" maxOccurs="unbounded">
<complexType>
<simpleContent>
<extension base="string">
<attribute name="name" type="string"/>
</extension>
</simpleContent>
</complexType>
</element>
</sequence>
</complexType>
</element>
</schema>
Note the following things about the XML Schema:
The Property element has the attribute maxOccurs="unbounded". This indicates that it is a repeating element.
The Property element is a complex type with simple content. This means it can have a text value and XML attributes.
Declare the type of Result using something like this:
<xsd:complexType name="ResultType">
<xsd:sequence>
<xsd:element ref="Target"/>
<xsd:element ref="Domain"/>
<xsd:element ref="Property"
minOccurs="0"
maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="rawScore" type="xsd:integer"/>
</xsd:complexType>
And learn the difference between elements and attributes, OK?

cvc-elt.1: Cannot find the declaration of element 'staff' - Cannot validate xml against a xsd

I can't validate xml document against xsd schema.
And I couldn't figure out what is wrong there.
Here is xml file:
<?xml version="1.0" encoding="UTF-8"?>
<staff xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="employee.xsd">
<employee>
<name>Carl Cracker</name>
<salary>75000</salary>
<hiredate year="1987" month="12" day="15" />
</employee>
<employee>
<name>Harry Hacker</name>
<salary>50000</salary>
<hiredate year="1989" month="10" day="1" />
</employee>
<employee>
<name>Tony Tester</name>
<salary>40000</salary>
<hiredate year="1990" month="3" day="15" />
</employee>
</staff>
And xsd file:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="staff">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="employee" maxOccurs="unbounded" minOccurs="0">
<xsd:complexType>
<xsd:sequence>
<xsd:element type="xsd:string" name="name"/>
<xsd:element type="xsd:int" name="salary"/>
<xsd:element name="hiredate">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute type="xsd:short" name="year" use="optional"/>
<xsd:attribute type="xsd:byte" name="month" use="optional"/>
<xsd:attribute type="xsd:byte" name="day" use="optional"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
And output is next:
cvc-elt.1: Cannot find the declaration of element 'staff'.
Exception in thread "main" java.lang.ClassCastException: com.sun.org.apache.xerces.internal.dom.DeferredTextImpl cannot be cast to org.w3c.dom.Element
at com.lab.edu.DOMTreeParser.parseStaff(DOMTreeParser.java:77)
at com.lab.edu.DOMTreeParser.<init>(DOMTreeParser.java:42)
at com.lab.edu.Application.main(Application.java:7)
Here is snippet of code:
public DOMTreeParser(String filename) {
employeeList = new ArrayList<>();
boolean result = validate(filename);
System.out.println("it is validate result: " + result);
if (result == false) {
System.out.println("XML isn't valid");
System.exit(0);
}
// if all are correct - parse xml
parseStaff(document.getDocumentElement());
}
private boolean validate(String filename) {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(true);
factory.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
factory.setIgnoringElementContentWhitespace(true);
builder = factory.newDocumentBuilder();
builder.setErrorHandler(new SimpleErrorHandler());
document = builder.parse(new File(filename));
return true;
} catch (ParserConfigurationException | SAXException | IOException e) {
e.printStackTrace();
return false;
}
}
I tried to validate xml accord xsd at validator - all was valid.
What is cause of this cvs.. message?
Any suggestions?
The outermost element of your instance document must match a global element declaration in the schema. You only have one global element declaration, for the "staff" element, which is not present in your instance. If you want the "employee" element to validate, you will have to promote it from a local element declaration to a global one, which means rewriting the schema as:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="staff">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="employee" maxOccurs="unbounded" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="employee">
<xsd:complexType>
<xsd:sequence>
<xsd:element type="xsd:string" name="name"/>
<xsd:element type="xsd:int" name="salary"/>
<xsd:element name="hiredate">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute type="xsd:short" name="year" use="optional"/>
<xsd:attribute type="xsd:byte" name="month" use="optional"/>
<xsd:attribute type="xsd:byte" name="day" use="optional"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>

Unmarshalling complex xml having nested child elements

I want to unmarshal a given xml file using jaxb2.
Here is the source xml document.
<?xml version="1.0" encoding="UTF-8"?>
<root>
<calendarList>
<calendar>
<calendarCode>Default</calendarCode>
<weeklyDefault>1111111</weeklyDefault>
<exceptionList>
<exception>
<exceptionDate>2012-03-01T00:00:00</exceptionDate>
<isOpen>false</isOpen>
</exception>
<exception>
<exceptionDate>2012-03-02T00:00:00</exceptionDate>
<isOpen>false</isOpen>
</exception>
</exceptionList>
</calendar>
<calendar/>
<calendarList>
</root>
for this I defined following xsd
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
jxb:version="2.0">
<xsd:element name="root" type="Root" />
<xsd:complexType name="Root">
<xsd:sequence>
<xsd:element name="calendarList" type="CalendarList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CalendarList">
<xsd:sequence>
<xsd:element name="calendar" type="Calendar" minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Calendar">
<xsd:sequence>
<xsd:element name="calendarCode" type="xsd:string" />
<xsd:element name="weeklyDefault" type="xsd:string" />
<xsd:element name="exceptionList" type="ExceptionList" minOccurs="0" maxOccurs="1" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="ExceptionList">
<xsd:sequence>
<xsd:element name="exceptionCalendar" type="ExceptionCalendar" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="ExceptionCalendar">
<xsd:sequence>
<xsd:element name="exceptionDate" type="xsd:dateTime" />
<xsd:element name="isOpen" type="xsd:boolean"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
Using JAXB I generated the classes for this but when I am unmarshalling I only able to get the Calendar Objects but not the nested "Exception" objects inside Calendar's ExceptionList.
Following code will explain above
public void CheckResults(filePath){
Root ods = handler.unmarshal(filePath);
for(Calendar calendar : ods.getCalendarList().getCalendar())
{
System.out.println(calendar.getCalendaeCode()); //Here I have the element calendar
//but calendar.getExceptionList().getExceptionCalendar() has no member
for (ExceptionCalendar expCal : calendar.getExceptionList().getExceptionCalendar())
{
System.out.println(expCal.getExceptionDate());
}
}
}
Here is the logic for handler.unmarshal method
public Root unmarshal(String filePath) {
try{
JAXBContext jc = JAXBContext.newInstance(DOMAIN_PKG);
Unmarshaller unmarsaller = jc.createUnmarshaller();
JAXBElement<Root> oDS;
if(filePath.isEmpty()) {
oDS = (JAXBElement<Root>) unmarsaller.unmarshal(System.in);
} else {
File file = new File(filePath);
oDS = (JAXBElement<Root>) unmarsaller.unmarshal(file);
}
return oDS.getValue();
}catch(JAXBException exp){
exp.printStackTrace();
}
return null;
}
It would be a great help if someone can explain how the object creation takes place while unmarshalling. Probably I am missing something small but important here.
I think your schema is wrong, replace name="ExceptionCalendar" by name="exception" and regenerate JAXB objects.
<xsd:complexType name="ExceptionList">
<xsd:sequence>
<xsd:element name="exception" type="ExceptionCalendar" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="ExceptionCalendar">
<xsd:sequence>
<xsd:element name="exceptionDate" type="xsd:dateTime" />
<xsd:element name="isOpen" type="xsd:boolean"/>
</xsd:sequence>
</xsd:complexType>

Getter on xmlbeans generated class returning null and it shouldn't

Using this simplified XSD (simplified, but still verbose as all XSDs tend to be):
<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="[redacted]">
<xsd:element name="Statement" type="BILLINGSTATEMENTTYPEType"/>
<xsd:complexType name="BILLINGSTATEMENTTYPEType">
<xsd:sequence>
<xsd:element name="AccountSection" type="ACCOUNTSECTIONTYPEType"/>
<xsd:element name="DataSection" type="DATASECTIONTYPEType"/>
<xsd:element name="Summary" type="SUMMARYTYPEType"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="ACCOUNTSECTIONTYPEType">
<xsd:sequence>
<xsd:element name="Foo" type="xsd:string" maxOccurs="unbounded" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="DATASECTIONTYPEType">
<xsd:sequence>
<xsd:element name="Bar" type="xsd:string" maxOccurs="unbounded" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="SUMMARYTYPEType">
<xsd:sequence>
<xsd:element name="Baz" type="xsd:string" maxOccurs="unbounded" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
I generated a JAR file (using the <xmlbean> Ant task from xmlbeans), and everything appears to look great, I get all the right types and whatnot. But when I have it parse this simplified document:
<Statement>
<AccountSection>
<Foo>bar</Foo>
</AccountSection>
<DataSection>
</DataSection>
<Summary>
</Summary>
</Statement>
Using this code:
public class XmlTest {
public static void main(String[] args) throws Exception {
File xmlFile = new File("./data/test.xml");
FileInputStream xmlStream = new FileInputStream(xmlFile);
BILLINGSTATEMENTTYPEType statement = BILLINGSTATEMENTTYPEType.Factory.parse(xmlStream);
ACCOUNTSECTIONTYPEType acctSection = statement.getAccountSection();
System.out.println(statement.xmlText());
System.out.println("acctSection is null:" + (acctSection == null));
}
}
The acctSection (and any of the child sections I've tried) are always null, even though it is fully parsing the document.
Output:
<Statement>
<AccountSection>
<Foo>bar</Foo>
</AccountSection>
<DataSection>
</DataSection>
<Summary>
</Summary>
</Statement>
acctSection is null:true
Why is it null? Why are they all null? Did I improperly define something somewhere in my XSD? I've used xmlbeans before successfully and never had this issue, which is why I'm sure I'm missing something but I've been unable to find it.
I'm not an export in xmlbeans myself, but I noticed that you used the Factory of the complex type to parse the xml. Can you try to use StatementDocument.Factory instead?
My problem was solved by adding elementFormDefault="qualified" in the namespace of my .xsd file.

Categories