6

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.

4

2 に答える 2

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

        }

    }
}
于 2013-06-05T08:31:25.990 に答える
2

最上位クラスの生成

Records クラスと別の Contract クラスだけを取得したい。

デフォルトでは、JAXB 実装は、匿名複合型に対応するクラスを静的内部クラスとして生成します。すべてをトップレベルクラスにしたい場合は、質問で述べたように、次の外部バインディングのカスタマイズを使用できます。

<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>

名前の競合の解決

エラーが発生します:

org.xml.sax.SAXParseException: A class/interface with the same name "com.my.package.Text

静的内部クラスの目的の 1 つは、名前の競合を防ぐことです。すべての最上位クラスで、外部バインディング ファイルを使用して、複合型から生成されたクラスの名前を変更できます。以下は、複合型 itemType に対応するクラスが 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>

バインディング ファイルの使用

-b フラグを使用して、XJC 呼び出しでバインディング ファイルを指定します。

xjc -b binding.xml your-schema.xsd

詳細については

于 2013-06-04T09:57:20.340 に答える