Java Jaxb Unmarshaller如何处理片段XML – XML的部分读取和写入

huangapple go评论76阅读模式
英文:

How does Java Jaxb Unmarshaller handle the fragment xml - the partial reading and writing of xml

问题

这一行会引发异常:

JAXBElement<Fruit> f_file = (JAXBElement<Fruit>) jaxbUnMarshallerFruit.unmarshal(new File("./fruit_in_basket.xml"));

异常的详细信息是:

javax.xml.bind.UnmarshalException: unexpected element (uri:"http://www.lin.com/", local:"fruit"). Expected elements are <{http://www.lin.com/}Document>

从异常信息来看,我猜测 Java 的 jaxbUnMarshaller 无法正确解析泛型类的信息。UnMarshaller 不能只解释 Fruit 类。如何修复它?

另外,还有一个小问题:
jaxbContext = JAXBContext.newInstance(Basket.class);
如果我使用 Basket.class,在解组时会出现错误:

unexpected element (uri:"http://www.lin.com/", local:"Document"). Expected elements are (none)

如果我传递 "com.baeldung.springsoap.basket",它可以正常工作。为什么?

(我已经搜索了一段时间,但也许我不能用准确的词语描述我的问题,所以我错过了一些东西。如果可能的话,请提供一些回答的链接。)

英文:

I have a XML file:

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;yes&quot;?&gt;
&lt;Document xmlns=&quot;http://www.lin.com/&quot;&gt;
    &lt;name&gt;basket1&lt;/name&gt;
    &lt;fruits id=&quot;1&quot;&gt;
        &lt;price&gt;9.99&lt;/price&gt;
        &lt;n&gt;Banana&lt;/n&gt;
    &lt;/fruits&gt;
    &lt;fruits id=&quot;2&quot;&gt;
        &lt;price&gt;19.99&lt;/price&gt;
        &lt;n&gt;Apple&lt;/n&gt;
    &lt;/fruits&gt;
&lt;/Document&gt;

I have entity classes:

package com.baeldung.springsoap.basket;

@XmlType(name = &quot;Document&quot;, propOrder = {&quot;name&quot;, &quot;fruits&quot;})
@XmlAccessorType(XmlAccessType.FIELD)
public class Basket {
    @XmlElement(name = &quot;name&quot;)
    private String name;
    @XmlElement(name = &quot;fruits&quot;, required = true)
    private List&lt;Fruit&gt; fruits;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List&lt;Fruit&gt; getFruits() {
        return fruits;
    }

    public void setFruits(List&lt;Fruit&gt; fruits) {
        this.fruits = fruits;
    }
}

@XmlType(propOrder = {&quot;price&quot;, &quot;name&quot;})
@XmlAccessorType(XmlAccessType.FIELD)
public class Fruit {

    @XmlAttribute
    int id;

    @XmlElement(name = &quot;n&quot;)
    String name;

    String price;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPrice() {
        return price;
    }

    public void setPrice(String price) {
        this.price = price;
    }
}

ObjectFactory.java is:

package com.baeldung.springsoap.basket;

import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.namespace.QName;


@XmlRegistry
public class ObjectFactory {

    private final static QName _Document_QNAME = new QName(&quot;http://www.lin.com/&quot;, &quot;Document&quot;);

    public Fruit createFruit() {
        return new Fruit();
    }

    @XmlElementDecl(namespace = &quot;http://www.lin.com/&quot;, name = &quot;Document&quot;)
    public JAXBElement&lt;Basket&gt; createBasket(Basket value) {
        return new JAXBElement&lt;Basket&gt;(_Document_QNAME, Basket.class, null, value);
    }

}

package-info.java is:

@javax.xml.bind.annotation.XmlSchema(namespace = &quot;http://www.lin.com/&quot;, elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package com.baeldung.springsoap.basket;

Java unmarshal and marshal code:

    public static void run_fruit() {
        try {
            //jaxbContext = JAXBContext.newInstance(Basket.class); // If I use Basket.class,  when unmarshal, it got error: unexpected element (uri:&quot;http://www.lin.com/&quot;, local:&quot;Document&quot;). Expected elements are (none)
            JAXBContext jaxbContext = JAXBContext.newInstance(&quot;com.baeldung.springsoap.basket&quot;); //

            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();

            JAXBElement&lt;Basket&gt; f = (JAXBElement&lt;Basket&gt;) jaxbUnmarshaller.unmarshal(new File(&quot;./basket_fruit.xml&quot;));

            // get a piece of fruit info, will save to file later.
            Basket bb = f.getValue();
            Fruit fruit=bb.getFruits().get(0);

            Marshaller jaxbMarshallerFruit = jaxbContext.createMarshaller();

            // save a piece of fruit info into file
            // in real scenario, we need get a fruit data from list, then save to db as row data.
            JAXBElement&lt;Fruit&gt; jaxbFruit= new JAXBElement&lt;&gt;(new QName(&quot;http://www.lin.com/&quot;, &quot;fruits&quot;), Fruit.class,  fruit);
            jaxbMarshallerFruit.marshal(jaxbFruit, new File(&quot;./fruit_in_basket.xml&quot;));

            // read fruit info from file, convert to java object.
            Unmarshaller jaxbUnMarshallerFruit = jaxbContext.createUnmarshaller();
            JAXBElement&lt;Fruit&gt; f_file = (JAXBElement&lt;Fruit&gt;) jaxbUnMarshallerFruit.unmarshal(new File(&quot;./fruit_in_basket.xml&quot;)); // this line will throw an exception.
            System.out.println(f_file);

        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }

This line will throw an exception.

JAXBElement&lt;Fruit&gt; f_file = (JAXBElement&lt;Fruit&gt;) jaxbUnMarshallerFruit.unmarshal(new File(&quot;./fruit_in_basket.xml&quot;)); 

The exception detail is:

javax.xml.bind.UnmarshalException: unexpected element (uri:&quot;http://www.lin.com/&quot;, local:&quot;fruit&quot;). Expected elements are &lt;{http://www.lin.com/}Document&gt;
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:726)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:247)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:242)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:109)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext$DefaultRootLoader.childElement(UnmarshallingContext.java:1131)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:556)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:538)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:153)
	at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:509)
	at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:374)
	at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl$NSContentDriver.scanRootElementHook(XMLNSDocumentScannerImpl.java:613)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3132)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:852)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:602)
	at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:112)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:505)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:842)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:771)
	at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
	at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213)
	at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:643)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:243)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:214)
	at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:157)
	at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:162)
	at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:171)
	at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:189)
	at com.baeldung.springsoap.xxml.JaxbExampleBasket.run_fruit(JaxbExampleBasket.java:48)
	at com.baeldung.springsoap.xxml.JaxbExampleBasket.main(JaxbExampleBasket.java:21)

From the exception, I guess the Java jaxbUnMarshaller can't figure out the authentic generics class info. UnMarshaller can't only interpret Fruit class. How to fix it?

Another minor question is:

jaxbContext = JAXBContext.newInstance(Basket.class); 

If I use Basket.class, when unmarshal, it will get an error:

unexpected element (uri:&quot;http://www.lin.com/&quot;, local:&quot;Document&quot;). Expected elements are (none)

If I pass &quot;com.baeldung.springsoap.basket&quot;, it works. Why?

(I have searched for a while, but maybe I can't describe my question with accurate words, so I missed something. If possible, kindly provide some links to the answer.)

答案1

得分: 0

Fruit 类添加 XMLRootElement 应该能消除异常。

@XmlRootElement(name = "fruits")
@XmlType(propOrder = {"price", "name"})
@XmlAccessorType(XmlAccessType.FIELD)
public class Fruit {
    // ...
}
英文:

Give the Fruit class an XMLRootElement should eliminate the exception.

@XmlRootElement(name = &quot;fruits&quot;)
@XmlType(propOrder = {&quot;price&quot;, &quot;name&quot;})
@XmlAccessorType(XmlAccessType.FIELD)
public class Fruit {
....

huangapple
  • 本文由 发表于 2023年3月7日 18:23:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/75660712.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定