原文: https://howtodoinjava.com/jaxb/unmarshal-without-xmlrootelement/

很多时候,您将需要解组不具有诸如@XmlRootElement之类的 JAXB 注解的 Java 对象,并且不允许您对源代码进行任何更改。 当您使用旧代码或某些您没有源代码的客户端 jar 时,可能会发生这种情况。

1.不带 JAXB 注解的解组问题

在这种情况下,如果您尝试直接将 Java 对象解组为 XML ,则将出现类似的错误。

  1. javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"employee"). Expected elements are (none)
  2. at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:726)
  3. at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:247)
  4. at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:242)
  5. at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:109)
  6. at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext$DefaultRootLoader.childElement(UnmarshallingContext.java:1131)
  7. at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:556)
  8. at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:538)
  9. at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:153)
  10. at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:509)
  11. at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:379)
  12. at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl$NSContentDriver.scanRootElementHook(XMLNSDocumentScannerImpl.java:605)
  13. at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3138)
  14. at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:880)
  15. at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:606)
  16. at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:117)
  17. at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510)
  18. at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:848)
  19. at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:777)
  20. at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
  21. at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213)
  22. at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:649)
  23. at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:243)
  24. at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:214)
  25. at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:157)
  26. at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:162)
  27. at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:171)
  28. at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:189)
  29. at com.howtodoinjava.demo.JaxbExample.jaxbXmlFileToObject(JaxbExample.java:63)
  30. at com.howtodoinjava.demo.JaxbExample.main(JaxbExample.java:21)

其中Employee.java类如下。 它没有任何@XmlRootElement这样的 JAXB 注解。

  1. package com.howtodoinjava.demo.model;
  2. import java.io.Serializable;
  3. public class Employee implements Serializable {
  4. private static final long serialVersionUID = 1L;
  5. private Integer id;
  6. private String firstName;
  7. private String lastName;
  8. private Department department;
  9. public Employee() {
  10. super();
  11. }
  12. public Employee(int id, String fName, String lName, Department department) {
  13. super();
  14. this.id = id;
  15. this.firstName = fName;
  16. this.lastName = lName;
  17. this.department = department;
  18. }
  19. //Getters and Setters
  20. @Override
  21. public String toString() {
  22. return "Employee [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", department="
  23. + department + "]";
  24. }
  25. }

2.不带 JAXB 注解的解组解决方案

缺少@XmlRootElement注解时,JAXB 无法为Employee对象构建JAXBElement实例。 因此,您必须在此帮助 JAXB 手动构建它。

2.1 语法

  1. /**
  2. * Unmarshal XML data from the specified XML Source by <tt>declaredType</tt> and return the
  3. * resulting content tree.
  4. * @param source source the XML Source to unmarshal XML data from (providers are
  5. * only required to support SAXSource, DOMSource, and StreamSource)
  6. *
  7. * @param declaredType appropriate JAXB mapped class to hold <tt>source</tt>'s xml root element
  8. *
  9. * @return value Java content rooted by JAXB Element
  10. */
  11. public <T> JAXBElement<T> unmarshal( javax.xml.transform.Source source, Class<T> declaredType )
  12. throws JAXBException;

例如:

  1. JAXBElement<Employee> jaxbElement = (JAXBElement<Employee>) jaxbUnmarshaller
  2. .unmarshal(new StreamSource(xmlFile), Employee.class);

2.2 解组

现在,让我们看看该解组代码的工作方式。

  1. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  2. <employee>
  3. <department>
  4. <id>101</id>
  5. <name>IT</name>
  6. </department>
  7. <firstName>Lokesh</firstName>
  8. <id>1</id>
  9. <lastName>Gupta</lastName>
  10. </employee>
  1. package com.howtodoinjava.demo;
  2. import java.io.File;
  3. import javax.xml.bind.JAXBContext;
  4. import javax.xml.bind.JAXBElement;
  5. import javax.xml.bind.JAXBException;
  6. import javax.xml.bind.Unmarshaller;
  7. import javax.xml.transform.stream.StreamSource;
  8. import com.howtodoinjava.demo.model.Employee;
  9. public class JaxbExample
  10. {
  11. public static void main(String[] args)
  12. {
  13. String fileName = "employee.xml";
  14. jaxbXmlFileToObject(fileName);
  15. }
  16. private static void jaxbXmlFileToObject(String fileName)
  17. {
  18. File xmlFile = new File(fileName);
  19. JAXBContext jaxbContext;
  20. try
  21. {
  22. jaxbContext = JAXBContext.newInstance(Employee.class);
  23. Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
  24. JAXBElement<Employee> jaxbElement = (JAXBElement<Employee>) jaxbUnmarshaller
  25. .unmarshal(new StreamSource(xmlFile), Employee.class);
  26. Employee employee = jaxbElement.getValue();
  27. System.out.println(employee);
  28. }
  29. catch (JAXBException e)
  30. {
  31. e.printStackTrace();
  32. }
  33. }
  34. }

程序输出:

  1. Employee [id=1, firstName=Lokesh, lastName=Gupta, department=Department [id=101, name=IT]]

将我的问题放在评论部分。

学习愉快!

参考: XmlRootElement Java 文档