XPATH不起作用

时间:2014-01-14 13:56:13

标签: java xml xpath xml-namespaces

我正在尝试使用XPath从请求中提取“PartyID”。此请求采用XML格式。

这是XML:

<?xml version="1.0" encoding="UTF-8"?>
    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"     xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<s1:invokerules xmlns:s1="http://rules.kmtool.abc.com"><s1:arg0><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
   <kbdInitiateRequest>
    <kmTestHeader>
        <MessageId>USER1_MSG1</MessageId>
            <TestDate>08/07/2008 07:34:15</TestDate>
            <TestReference>
            <ConductorReference>
                <InvokeIdentifier>
                    <RefNum>USER1_Ref1</RefNum>
                </InvokeIdentifier>
            </ConductorReference>
        </TestReference>
        <TestParty>
            <ConductorParty>
                <Party PartyID="123456789" AgencyID="DUNS">
                    <TestContact>
                        <DetailedContact>
                                                <ContactName>Michael Jackson</ContactName>
                            <Telephone>02071059053</Telephone>
                            <TelephoneExtension>4777</TelephoneExtension>
                            <Email>Michal.Jackson@Neverland.com</Email>
                            <Title>Mr</Title>
                            <FirstName>Michael</FirstName>
                            <Initials>MJ</Initials>
                        </DetailedContact>
                    </TestContact>
                </Party>
            </ConductorParty>
            <PerformerParty>
                <Party PartyID="987654321" AgencyID="DUNS">
                </Party>
            </PerformerParty>
        </TestParty>
    </kmTestHeader>
    <kmToolMessage>
        <controlNode>
            <userRequest>INITIATE</userRequest>
        </controlNode>
        <customer>
            <circuitID>000111333777</circuitID>
    </customer>
</kmToolMessage> 
</kbdInitiateRequest>

]]></s1:arg0>
</s1:invokerules>
</soapenv:Body>
</soapenv:Envelope>

我的java代码中有一个名为getPartyId()的方法。此方法应从XML中提取PartyID。但是,无论我使用什么XPath查询,我都无法使用此方法返回PartyID,这是我需要帮助的地方。

这是getPartyId方法:

private String getPartyId(String xml) throws XPathExpressionException
    {       
        XPathFactory xPathfactory = XPathFactory.newInstance();
        XPath xpath = xPathfactory.newXPath();      
        xpath.setNamespaceContext(new NamespaceContext() {
            public String getNamespaceURI(String prefix) {
                if (prefix == null) throw new NullPointerException("Null prefix");
                else if ("SOAP-ENV".equals(prefix)) return "http://schemas.xmlsoap.org/soap/envelope/";
                else if ("xml".equals(prefix)) return XMLConstants.XML_NS_URI;
                return XMLConstants.NULL_NS_URI;
            }

            public String getPrefix(String uri) {
                throw new UnsupportedOperationException();
            }

            public Iterator getPrefixes(String uri) {
                throw new UnsupportedOperationException();
            }
        });

        XPathExpression expr = xpath.compile("/SOAP-ENV:Envelope/SOAP-ENV:Body/*/*/*/*/*/*/*/*/*/*/*[local-name()='PartyID']/text()");

        InputSource source = new InputSource(new StringReader(xml));

        String dunsId = (String) expr.evaluate(source,XPathConstants.STRING);

        return dunsId;
    }

我认为问题在于XPathExpression:

XPathExpression expr = xpath.compile("/SOAP-ENV:Envelope/SOAP-ENV:Body/*/*/*/*/*/*/*/*/*/*/*[local-name()='PartyID']/text()");

我为'expr'尝试了许多替代品,但这些都没有奏效。有没有人有任何想法?

2 个答案:

答案 0 :(得分:1)

由于您需要解析的xml位于CDATA块内,因此在访问其中的数据之前,您需要重新解析s1:arg0的值。

您需要分两步完成此操作

  • 您需要访问arg0命名空间中的http://rules.kmtool.abc.com节点。

由于此内部xmlns没有NamespaceContext,因此您可以使用:

/SOAP-ENV:Envelope/SOAP-ENV:Body/*[local-name()='invokerules'] /*[local-name()='arg0']/text()

  • 然后,您需要将此值加载到另一个InputSource。 可以通过以下路径访问PartyId属性:

kbdInitiateRequest/kmTestHeader/TestParty/ConductorParty/Party/@PartyID

(由于local-name()中没有xmlns,因此无需使用CDATA

答案 1 :(得分:0)

请注意,您的内部xml位于CDATA节点内。 所以基本上你是在尝试查询CDATA内的XML路径。

作为这个线程状态 Xpath to the tag inside CDATA

似乎这是不可能的:(

我建议将代码中的CData解析为新的XML文档并进行查询。

谢谢, 阿米尔