不带 jaxb 注解的解组

不带 jaxb 注解的解组

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

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

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

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

javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"employee"). Expected elements are (none)
	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:379)
	at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl$NSContentDriver.scanRootElementHook(XMLNSDocumentScannerImpl.java:605)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3138)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:880)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:606)
	at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:117)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:848)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:777)
	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:649)
	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.howtodoinjava.demo.JaxbExample.jaxbXmlFileToObject(JaxbExample.java:63)
	at com.howtodoinjava.demo.JaxbExample.main(JaxbExample.java:21)

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

package com.howtodoinjava.demo.model;

import java.io.Serializable;

public class Employee implements Serializable {

	private static final long serialVersionUID = 1L;

	private Integer id;
	private String firstName;
	private String lastName;
	private Department department;

	public Employee() {
		super();
	}

	public Employee(int id, String fName, String lName, Department department) {
		super();
		this.id = id;
		this.firstName = fName;
		this.lastName = lName;
		this.department = department;
	}

	//Getters and Setters

	@Override
	public String toString() {
		return "Employee [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", department="
				+ department + "]";
	}
}

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

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

2.1 语法

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

例如:

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

2.2 解组

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

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<employee>
    <department>
        <id>101</id>
        <name>IT</name>
    </department>
    <firstName>Lokesh</firstName>
    <id>1</id>
    <lastName>Gupta</lastName>
</employee>

package com.howtodoinjava.demo;

import java.io.File;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;

import com.howtodoinjava.demo.model.Employee;

public class JaxbExample 
{
	public static void main(String[] args) 
	{
		String fileName = "employee.xml";

		jaxbXmlFileToObject(fileName);
	}

	private static void jaxbXmlFileToObject(String fileName) 
	{
		File xmlFile = new File(fileName);
		JAXBContext jaxbContext;
		try 
		{
			jaxbContext = JAXBContext.newInstance(Employee.class);
			Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();

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

			Employee employee = jaxbElement.getValue();

			System.out.println(employee);
		}
		catch (JAXBException e) 
		{
			e.printStackTrace();
		}
	}
}

程序输出:

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

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

学习愉快!

参考: XmlRootElement Java 文档