简体   繁体   English

在 Java 中使用 XPath 解析 SOAP 消息

[英]Parsing a SOAP message using XPath in Java

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <soap:Body>
        <ParentNode xmlns="http://namespace">
            <Status>Some_status</Satus>
            <Data>
                <Row>Some_row_data</Row>
            </Data>
        </ParentNode>
    </soap:Body>
</soap:Envelope>

A SOAP message similar in structure to the above is produced in an API call在 API 调用中产生结构与上述类似的 SOAP 消息

SOAPMessage soapMessage = getSoapMessage()

What I want to do is to be able to run xPath queries on top of my sope message, ie I'd like to get the data in the Row node.我想要做的是能够在我的 sope 消息之上运行 xPath 查询,即我想在 Row 节点中获取数据。

What I've done:我所做的:

XPathFactory xPathFactory = XPathFactory.newInstance();
XPath xPath = xPathFactory.newXPath();
xPath.setNamespaceContext(new NamespaceContext() {
      @Override
      public String getNamespaceURI(String prefix) {
        return "http://namespace";
      }

      @Override
      public String getPrefix(String namespaceURI) {
        return null;
      }

      @Override
      public Iterator getPrefixes(String namespaceURI) {
        System.out.println(namespaceURI);
        return null;
      }
    });

SOAPBody body = soapMessage.getSoapBody();
Document document = body.extractContentAsDocument();

NodeList list = (NodeList)xPath.compile("/").evaluate(document, XPathConstants.NODESET);
Node node = list.item(0);
System.out.println(node.getFirstChild().getNodeName());

Running this on the root node is all well and good, ParentNode gets printed to the console.在根节点上运行它一切顺利, ParentNode被打印到控制台。

However, setting replacing my xPath evaluation with the following:但是,设置用以下内容替换我的 xPath 评估:

NodeList list = (NodeList)xPath.compile("/ParentNode").evaluate(document, XPathConstants.NODESET);

results in an empty list.结果是一个空列表。 I assumed it had something to do with namespaces so I replaced my query with the following:我认为它与命名空间有关,所以我用以下内容替换了我的查询:

NodeList list = (NodeList)xPath.compile("/*[name()='ParentNode']").evaluate(document, XPathConstants.NODESET);

and this seems to work ok.似乎工作正常。 My question is, how do I properly set the namespace context so that I can use xPath querying without the name()=... surrounding every node?我的问题是,如何正确设置命名空间上下文,以便我可以在没有name()=...围绕每个节点的情况下使用 xPath 查询? Do I need to use a DocumentBuilder factory and set its namespace aware to true?我是否需要使用 DocumentBuilder 工厂并将其命名空间感知设置为 true? If so, how do I feed this SOAP message into that factory?如果是这样,我如何将此 SOAP 消息提供给该工厂?

As har07 suggested, adding an arbitrary prefix to my xPath queries was the trick to having my namespace be resolved properly.正如har07 所建议的,向我的 xPath 查询添加任意前缀是正确解析我的命名空间的诀窍。 As a result, the following query worked:结果,以下查询有效:

NodeList list = (NodeList)xPath.compile("/arbitraryprefix:ParentNode").evaluate(document, XPathConstants.NODESET);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM