猿问

JAXB - 转换其中包含 XSD/命名空间引用的 XML 文件

如何将带有 XSD/命名空间的 XML 转换为对象?

我收到此错误:

javax.xml.bind.UnmarshalException:意外元素(uri:“ http://www.opengis.net/wfs/2.0 ”,本地:“FeatureCollection”)。预期的元素是 <{}FeatureCollection>

这是示例 XML:

<wfs:FeatureCollection xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fes="http://www.opengis.net/fes/2.0" xmlns:wfs="http://www.opengis.net/wfs/2.0" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" numberMatched="7961422" numberReturned="0" timeStamp="2019-07-16T09:44:51.540Z" xsi:schemaLocation="http://www.opengis.net/wfs/2.0 http://schemas.opengis.net/wfs/2.0/wfs.xsd"/>

我的简单 JAXB 转换器是:

public static Object convertXmlToObject(String xmlString, Class targetClass) {

    JAXBContext jaxbContext;

    try {

        jaxbContext = JAXBContext.newInstance( targetClass);

        Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();

        return jaxbUnmarshaller.unmarshal(new StringReader(xmlString));

    } catch (JAXBException e) {

        e.printStackTrace();

        return null;

    }

}

这个方法的调用是:


TargetObject to = (TargetObject) converter.convertXmlToObject( xmlString, TargetObject.class);

目标对象是:


@XmlRootElement( name="FeatureCollection")

public class TargetObject {

    private long numberMatched = -1;

    private long numberReturned = -1;

    private LocalDateTime timeStamp;

    // ... all getters

    @XmlAttribute

    public void setNumberMatched(long numberMatched) {

        this.numberMatched = numberMatched;

    }

    @XmlAttribute

    public void setNumberReturned(long numberReturned) {

        this.numberReturned = numberReturned;

    }

    @XmlAttribute

    @XmlJavaTypeAdapter(value = LocalDateTimeAdapter.class)

    public void setTimeStamp(LocalDateTime timeStamp) {

        this.timeStamp = timeStamp;

    }

}

如何改进我的代码以将 XML 字符串转换为对象?


饮歌长啸
浏览 149回答 1
1回答

扬帆大鱼

享受这个通用的解决方案:转换器类Junit 测试——显示了 1 个没有名称空间的测试,但它确实适用于名称空间使用 XSLT 剥离名称空间的转换器类。JAXB 有时过于直白,您可以在许多帖子中看到这一点。public class XmlToPojo {&nbsp; &nbsp; public static Object convertXmlToObject(String xmlString, Class targetClass) {&nbsp; &nbsp; &nbsp; &nbsp; JAXBContext jaxbContext;&nbsp; &nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Step 1 - remove namespaces&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; StreamSource xmlSource = new StreamSource(new StringReader(xmlString));&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; StreamResult result = new StreamResult(new StringWriter());&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; removeNamespace(xmlSource, result);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Step 2 - convert XML to object&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; jaxbContext = JAXBContext.newInstance(targetClass);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return jaxbUnmarshaller.unmarshal(new StringReader(result.getWriter().toString()));&nbsp; &nbsp; &nbsp; &nbsp; } catch (Exception e) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e.printStackTrace();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return null;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; // Remove namespaces from XML&nbsp; &nbsp; private static String xsltNameSpaceRemover = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">\n" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "\n" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "&nbsp; &nbsp; <xsl:output indent=\"yes\" method=\"xml\" encoding=\"utf-8\" omit-xml-declaration=\"yes\"/>\n" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "\n" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "&nbsp; &nbsp; <!-- Stylesheet to remove all namespaces from a document -->\n" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "&nbsp; &nbsp; <!-- NOTE: this will lead to attribute name clash, if an element contains\n" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "&nbsp; &nbsp; &nbsp; &nbsp; two attributes with same local name but different namespace prefix -->\n" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "&nbsp; &nbsp; <!-- Nodes that cannot have a namespace are copied as such -->\n" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "\n" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "&nbsp; &nbsp; <!-- template to copy elements -->\n" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "&nbsp; &nbsp; <xsl:template match=\"*\">\n" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "&nbsp; &nbsp; &nbsp; &nbsp; <xsl:element name=\"{local-name()}\">\n" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <xsl:apply-templates select=\"@* | node()\"/>\n" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "&nbsp; &nbsp; &nbsp; &nbsp; </xsl:element>\n" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "&nbsp; &nbsp; </xsl:template>\n" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "\n" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "&nbsp; &nbsp; <!-- template to copy attributes -->\n" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "&nbsp; &nbsp; <xsl:template match=\"@*\">\n" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "&nbsp; &nbsp; &nbsp; &nbsp; <xsl:attribute name=\"{local-name()}\">\n" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <xsl:value-of select=\".\"/>\n" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "&nbsp; &nbsp; &nbsp; &nbsp; </xsl:attribute>\n" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "&nbsp; &nbsp; </xsl:template>\n" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "\n" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "&nbsp; &nbsp; <!-- template to copy the rest of the nodes -->\n" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "&nbsp; &nbsp; <xsl:template match=\"comment() | text() | processing-instruction()\">\n" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "&nbsp; &nbsp; &nbsp; &nbsp; <xsl:copy/>\n" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "&nbsp; &nbsp; </xsl:template>\n" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "\n" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "</xsl:stylesheet>";&nbsp; &nbsp; private static void removeNamespace(Source xmlSource, Result xmlOutput) throws TransformerException {&nbsp; &nbsp; &nbsp; &nbsp; TransformerFactory factory = TransformerFactory.newInstance();&nbsp; &nbsp; &nbsp; &nbsp; StreamSource xsltSource = new StreamSource(new StringReader(xsltNameSpaceRemover));&nbsp; &nbsp; &nbsp; &nbsp; Transformer transformer = factory.newTransformer(xsltSource);&nbsp; &nbsp; &nbsp; &nbsp; transformer.transform(xmlSource, xmlOutput);&nbsp; &nbsp; }}一个简单的 Junit 测试:public class XmlToPojoTest {&nbsp; &nbsp; @Test&nbsp; &nbsp; public void testBasic() {&nbsp; &nbsp; &nbsp; &nbsp; String xmlString = "<employee>" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "&nbsp; &nbsp; <department>" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "&nbsp; &nbsp; &nbsp; &nbsp; <id>101</id>" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "&nbsp; &nbsp; &nbsp; &nbsp; <name>IT-ABC</name>" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "&nbsp; &nbsp; </department>" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "&nbsp; &nbsp; <firstName>JJ</firstName>" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "&nbsp; &nbsp; <id>1</id>" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "&nbsp; &nbsp; <lastName>JoHo</lastName>" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "</employee>";&nbsp; &nbsp; &nbsp; &nbsp; XmlToPojo xmlToPojo = new XmlToPojo();&nbsp; &nbsp; &nbsp; &nbsp; Employee emp = (Employee) xmlToPojo.convertXmlToObject(xmlString, Employee.class);&nbsp; &nbsp; &nbsp; &nbsp; assertEquals("JJ", emp.getFirstName());&nbsp; &nbsp; &nbsp; &nbsp; assertEquals("IT-ABC", emp.getDepartment().getName());&nbsp; &nbsp; }}
随时随地看视频慕课网APP

相关分类

Java
我要回答