Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为JAXB.unmarshal()提取XML节点的最简单方法是什么?_Java_Jaxb_Cxf_Unmarshalling_Wsdl2java - Fatal编程技术网

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

Java 为JAXB.unmarshal()提取XML节点的最简单方法是什么?,java,jaxb,cxf,unmarshalling,wsdl2java,Java,Jaxb,Cxf,Unmarshalling,Wsdl2java,我使用cxfcodegenplugin的wsdl2java目标从WSDL生成Java。然后,在测试中,我使用JAXB.unmarshal()从原始webservice XML结果填充类 一个典型的例子是GetAllResponseType response=unmarshal(“get all.xml”,GetAllResponseType.class),使用以下方法: <T> T unmarshal(String filename, Class<T> clazz) th

我使用
cxfcodegenplugin
wsdl2java
目标从WSDL生成Java。然后,在测试中,我使用JAXB.unmarshal()从原始webservice XML结果填充类

一个典型的例子是
GetAllResponseType response=unmarshal(“get all.xml”,GetAllResponseType.class)
,使用以下方法:

<T> T unmarshal(String filename, Class<T> clazz) throws Exception {
    InputStream body = getClass().getResourceAsStream(filename);
    return javax.xml.bind.JAXB.unmarshal(body, clazz);
}
T unmarshal(字符串文件名,类clazz)引发异常{
InputStream body=getClass().getResourceAsStream(文件名);
返回javax.xml.bind.JAXB.unmarshal(body,clazz);
}
问题在于:原始XML响应总是包含信封和正文标记,这些标记不是由wsdl2java作为类生成的:

<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>

...
因此,为了使用JAXB.unmarshal(),我必须

  • 或者在get-all.xml中手动去除周围的信封/正文标记
  • 或者提取getAllResponse节点并将其重新转换为InputStream
  • 或者创建封套和主体类
  • 目前我有2,但代码很多:

    <T> T unmarshal(String filename, Class<T> clazz) throws Exception {
        InputStream is = getClass().getResourceAsStream(filename);
        InputStream body = nodeContent(is, "n4:Body");
        return javax.xml.bind.JAXB.unmarshal(body, clazz);
    }
    
    InputStream nodeContent(InputStream is, String name) throws Exception {
        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
        Document doc = docBuilder.parse(is);
        Node node = firstNonTextNode(doc.getElementsByTagName(name).item(0).getChildNodes());
        return nodeToStream(node);
    }
    
    Node firstNonTextNode(NodeList nl) {
        for (int i = 0; i < nl.getLength(); i++) {
            if (!(nl.item(i) instanceof Text)) {
                return nl.item(i);
            }
        }
        throw new RuntimeException("Couldn't find nontext node");
    }
    
    InputStream nodeToStream(Node node) throws Exception {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        Source xmlSource = new DOMSource(node);
        Result outputTarget = new StreamResult(outputStream);
        TransformerFactory.newInstance().newTransformer().transform(xmlSource, outputTarget);
        return new ByteArrayInputStream(outputStream.toByteArray());
    }
    
    T unmarshal(字符串文件名,类clazz)引发异常{
    InputStream=getClass().getResourceAsStream(文件名);
    InputStream主体=节点内容(即“n4:body”);
    返回javax.xml.bind.JAXB.unmarshal(body,clazz);
    }
    InputStream nodeContent(InputStream为,字符串名称)引发异常{
    DocumentBuilderFactory docFactory=DocumentBuilderFactory.newInstance();
    DocumentBuilder docBuilder=docFactory.newDocumentBuilder();
    Document doc=docBuilder.parse(is);
    Node Node=firstNonTextNode(doc.getElementsByTagName(name).item(0).getChildNodes());
    返回nodeToStream(node);
    }
    节点第一个非文本节点(节点列表nl){
    对于(int i=0;i
    我的问题是:

    • 2中是否有更简单的提取方法?我很想做一个regexp。我尝试了XPath,但不知怎的,我无法让它工作。代码示例会很有帮助
    • 我可以让wsdl2java创建Body/Envelope类(3),还是自己创建它们比较容易
    您可以使用StAX
    XmlStreamReader
    解析XML,然后将其推进到要解组的元素,并让您的JAXB实现解组该
    XmlStreamReader

    了解更多信息


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

    <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();
    }
    
    T unmarshal(字符串文件名,类clazz)引发异常{
    XMLInputFactory xif=XMLInputFactory.newFactory();
    XMLStreamReader xsr=xif.createXMLStreamReader(getClass().getResourceAsStream(文件名));
    xsr.nextTag();
    而(!xsr.getLocalName().equals(“Body”)){
    xsr.nextTag();
    }
    xsr.nextTag();
    Unmarshaller Unmarshaller=JAXBContext.newInstance(clazz.createUnmarshaller();
    返回unmarshaller.unmarshal(xsr,clazz.getValue();
    }
    

    感谢Blaise Doughan在这个问题上的帮助。

    使用
    DOMSource
    传递节点作为输入。下面的方法将
    org.w3c.dom.Node
    作为输入,并返回未编组的类

    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();
    }
    
    private T unmarshal(节点,类clazz)抛出jaxbeexception{
    XMLInputFactory XMLInputFactory=XMLInputFactory.newFactory();
    Source xmlSource=新的DOMSource(节点);
    Unmarshaller Unmarshaller=JAXBContext.newInstance(clazz.createUnmarshaller();
    返回unmarshaller.unmarshal(xmlSource,clazz.getValue();
    }