英文:
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:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Document xmlns="http://www.lin.com/">
<name>basket1</name>
<fruits id="1">
<price>9.99</price>
<n>Banana</n>
</fruits>
<fruits id="2">
<price>19.99</price>
<n>Apple</n>
</fruits>
</Document>
I have entity classes:
package com.baeldung.springsoap.basket;
@XmlType(name = "Document", propOrder = {"name", "fruits"})
@XmlAccessorType(XmlAccessType.FIELD)
public class Basket {
@XmlElement(name = "name")
private String name;
@XmlElement(name = "fruits", required = true)
private List<Fruit> fruits;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Fruit> getFruits() {
return fruits;
}
public void setFruits(List<Fruit> fruits) {
this.fruits = fruits;
}
}
@XmlType(propOrder = {"price", "name"})
@XmlAccessorType(XmlAccessType.FIELD)
public class Fruit {
@XmlAttribute
int id;
@XmlElement(name = "n")
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("http://www.lin.com/", "Document");
public Fruit createFruit() {
return new Fruit();
}
@XmlElementDecl(namespace = "http://www.lin.com/", name = "Document")
public JAXBElement<Basket> createBasket(Basket value) {
return new JAXBElement<Basket>(_Document_QNAME, Basket.class, null, value);
}
}
package-info.java is:
@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.lin.com/", 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:"http://www.lin.com/", local:"Document"). Expected elements are (none)
JAXBContext jaxbContext = JAXBContext.newInstance("com.baeldung.springsoap.basket"); //
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
JAXBElement<Basket> f = (JAXBElement<Basket>) jaxbUnmarshaller.unmarshal(new File("./basket_fruit.xml"));
// 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<Fruit> jaxbFruit= new JAXBElement<>(new QName("http://www.lin.com/", "fruits"), Fruit.class, fruit);
jaxbMarshallerFruit.marshal(jaxbFruit, new File("./fruit_in_basket.xml"));
// read fruit info from file, convert to java object.
Unmarshaller jaxbUnMarshallerFruit = jaxbContext.createUnmarshaller();
JAXBElement<Fruit> f_file = (JAXBElement<Fruit>) jaxbUnMarshallerFruit.unmarshal(new File("./fruit_in_basket.xml")); // this line will throw an exception.
System.out.println(f_file);
} catch (JAXBException e) {
e.printStackTrace();
}
}
This line will throw an exception.
JAXBElement<Fruit> f_file = (JAXBElement<Fruit>) jaxbUnMarshallerFruit.unmarshal(new File("./fruit_in_basket.xml"));
The exception detail is:
javax.xml.bind.UnmarshalException: unexpected element (uri:"http://www.lin.com/", local:"fruit"). Expected elements are <{http://www.lin.com/}Document>
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:"http://www.lin.com/", local:"Document"). Expected elements are (none)
If I pass "com.baeldung.springsoap.basket"
, 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 = "fruits")
@XmlType(propOrder = {"price", "name"})
@XmlAccessorType(XmlAccessType.FIELD)
public class Fruit {
....
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论