7

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.

Community
  • 1
  • 1
Ruslan
  • 14,229
  • 8
  • 49
  • 67

2 Answers2

13
/**
 * 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();
            }

        }

    }
}
Ruslan
  • 14,229
  • 8
  • 49
  • 67
  • Hi, I am trying to something similar but its not working as expected for me. I have posted the question here. If you get a chance can you please have a look and provide your suggestion? https://stackoverflow.com/questions/67676591/unable-to-unmarshal-the-xml-to-my-class-using-the-xmleventreader – BATMAN_2008 May 24 '21 at 17:52
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

bdoughan
  • 147,609
  • 23
  • 300
  • 400
  • You already ask my other question :) This question, about how to make separate class. – Ruslan Jun 04 '13 at 09:59
  • Or, about, how to partionally unmarshall following structure. – Ruslan Jun 04 '13 at 10:00
  • @IRus - My current answer will help you with the `same name` error you are seeing. I don't understand the partial unmarshal part of your question. – bdoughan Jun 04 '13 at 10:07
  • Too many classes to rename. Big work, scheme can be changed -> not solution. – Ruslan Jun 04 '13 at 11:06
  • @IRus - I would recommend keeping the static inner classes to reduce the number of name conflicts. – bdoughan Jun 04 '13 at 13:31
  • ok, in this case, if i keep the inner classes, how to **unmarshal big xml by chunks**? I need get set of **Contract** objects. – Ruslan Jun 05 '13 at 07:05
  • @IRus - Static inner classes have the same capabilities as top level classes, so having them isn't a restriction. – bdoughan Jun 05 '13 at 10:06