问题
I want do partial unmarshaling of big XML.
XML has following structure:
<Records>
<Contract>
...
</Contract>
<Contract>
...
</Contract>
...
<Contract>
...
</Contract>
<Contract>
...
</Contract>
</Records>
And result class generated with XJC:
- Records
|- Contract
If i follow these(sample from jaxb-ri), i get error:
Exception in thread "main" javax.xml.bind.UnmarshalException: unexpected element (uri:"http://somedomain.com", local:"Contract"). Expected elements are <{http://somedomain.com}Records>
If i use:
<jaxb:globalBindings localScoping="toplevel"/>
I get error:
org.xml.sax.SAXParseException: A class/interface with the same name "com.my.package.Text" is already in use. Use a class customization to resolve this conflict.
But i need change many classes. And this is not solution.
回答1:
/**
* User: r.ibragimov
* Date: 04.06.13
*/
public class PartialJAXB1 {
public static void main(String[] args) throws JAXBException, XMLStreamException, FileNotFoundException {
final QName qName = new QName("http://www.domain.com","Contract");
InputStream inputStream = new FileInputStream(new File("c:\\test.xml"));
// create xml event reader for input stream
XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
XMLEventReader xmlEventReader = xmlInputFactory.createXMLEventReader(inputStream);
// initialize jaxb
JAXBContext context = JAXBContext.newInstance(Records.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
XMLEvent e = null;
// loop though the xml stream
while( (e = xmlEventReader.peek()) != null ) {
// check the event is a Document start element
if(e.isStartElement() && ((StartElement)e).getName().equals(qName)) {
// unmarshall the document
Records.Contract contract = unmarshaller.unmarshal(xmlEventReader, Records.Contract.class).getValue();
System.out.println(contract);
} else {
xmlEventReader.next();
}
}
}
}
回答2:
Generating Top Level Classes
I want get just Records class and separate Contract class.
By default a JAXB implementation will generate classes corresponding to anonymous complex types as static inner classes. If you want everything to be a top level class you can as you stated in your question use the following external binding customization:
<jaxb:bindings
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
version="2.1">
<jaxb:globalBindings localScoping="toplevel"/>
</jaxb:bindings>
Resolving Name Conflicts
I get error:
org.xml.sax.SAXParseException: A class/interface with the same name "com.my.package.Text
One of the purposes of the static inner classes is to prevent name conflicts. With all top level classes you can use an external binding file to rename the class generated from a complex type. Below is an example where the class corresponding to the complex type itemType would be generated as Item.
<jaxb:bindings
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
version="2.1">
<jaxb:globalBindings localScoping="toplevel"/>
<jaxb:bindings schemaLocation="company.xsd">
<jaxb:bindings node="//xsd:element[@name='employee']/xsd:complexType/xsd:sequence/xsd:element[@name='address']/xsd:complexType">
<jaxb:class name="EmployeeAddress"/>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
Using the Binding File
You specify the binding file in the XJC call using the -b flag
xjc -b binding.xml your-schema.xsd
For More Information
- http://blog.bdoughan.com/2011/07/jaxb-xjc-and-nested-classes.html
来源:https://stackoverflow.com/questions/16914628/partial-unmarshalling-with-jaxb