为JAXB.unmarshal()提取XML节点的最简单方法是什么?

时间:2013-06-10 07:21:35

标签: java jaxb cxf unmarshalling wsdl2java

我使用wsdl2java的{​​{1}}目标从WSDL生成Java。然后,在我的测试中,我使用JAXB.unmarshal()从原始Web服务XML结果中填充类。

一个典型的例子是cxf-codegen-plugin,使用以下方法:

GetAllResponseType response = unmarshal("get-all.xml", GetAllResponseType.class)

问题是这样的:原始XML响应总是包含由wsdl2java不作为类生成的Envelope和Body标记:

<T> T unmarshal(String filename, Class<T> clazz) throws Exception {
    InputStream body = getClass().getResourceAsStream(filename);
    return javax.xml.bind.JAXB.unmarshal(body, clazz);
}

所以,为了使用JAXB.unmarshal()我必须

  1. 在get-all.xml
  2. 中手动删除周围的Envelope / Body标记
  3. 或解压缩getAllResponse节点并将其重新转换为InputStream
  4. 或创建信封和身体类
  5. 目前我做 2 ,但这是很多代码:

    <n4:Envelope xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:n="http://www.informatica.com/wsdl/"
             xmlns:n4="http://schemas.xmlsoap.org/soap/envelope/" xmlns:n5="http://schemas.xmlsoap.org/wsdl/"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <n4:Body>
        <n:getAllResponse xmlns:n="http://www.informatica.com/wsdl/">
            <n:getAllResponseElement>
               ...
            </n:getAllResponseElement>
        </n:getAllResponse>
      </n4:Body>
    </n4:Envelope>
    

    我的问题是:

    • 2 中有更简单的提取方法吗?我很想做一个正则表达式。我试过XPath,但不知怎的,我无法让它工作。代码示例会有所帮助。
    • 我可以让wsdl2java创建Body / Envelope类( 3 ),还是自己创建它们很容易?

3 个答案:

答案 0 :(得分:2)

n4:Body节点中的节点可以使用XMLStreamReader和“原始”JAXB Unmarshaller进行解组:

<T> T unmarshal(String filename, Class<T> clazz) throws Exception {
    XMLInputFactory xif = XMLInputFactory.newFactory();
    XMLStreamReader xsr = xif.createXMLStreamReader(getClass().getResourceAsStream(filename));
    xsr.nextTag();
    while (!xsr.getLocalName().equals("Body")) {
        xsr.nextTag();
    }
    xsr.nextTag();
    Unmarshaller unmarshaller = JAXBContext.newInstance(clazz).createUnmarshaller();
    return unmarshaller.unmarshal(xsr, clazz).getValue();
}

感谢Blaise Doughan帮助解决这个问题。

答案 1 :(得分:1)

您可以使用StAX XmlStreamReader来解析XML,然后将其推进到要解组的元素,并让您的JAXB实现解组为XmlStreamReader

了解更多信息

答案 2 :(得分:0)

使用DOMSource传递节点作为输入。以下方法将org.w3c.dom.Node作为输入并返回unmarshalled类。

private <T> T unmarshal(Node node, Class<T> clazz) throws JAXBException {
        XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory();
        Source xmlSource = new DOMSource(node);
        Unmarshaller unmarshaller = JAXBContext.newInstance(clazz).createUnmarshaller();
        return unmarshaller.unmarshal(xmlSource, clazz).getValue();
}