在Java中使用Xpath定位具有特定namepace的元素

时间:2019-09-17 07:51:07

标签: java xml xpath xml-namespaces

我正在尝试使用Java中的Xpath列出具有特定名称空间的元素。 我有以下xml文件:

<pd:ProcessDefinition xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  xmlns:pd="http://newsample/cred/process/2007"  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<pd:name>Processes/Schemas/GetInline.process</pd:name>
<pd:startName>StartThis</pd:startName>
<pd:startType>
    <xsd:element name="root">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name="param" type="xsd:string"/>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
</pd:startType>
<pd:endName>End</pd:endName>
<pd:endType>
    <xsd:element name="End" type="xsd:string"/>
</pd:endType>
<pd:activity name="MapAnyelement">
    <config>
        <element>
            <xsd:choice>
                <xsd:element name="param" type="xsd:string"/>
                <xsd:element ref="pfx:param1"/>
            </xsd:choice>
        </element>
    </config>
    <pd:coercions>
        <pd:coercion xpath="root" element="pfx:param1"/>
    </pd:coercions>
    <pd:inputBindings/>
</pd:activity>
<pd:activity name="MapComplex">
    <config>
        <element>
            <xsd:element name="mapComplex">
                <xsd:complexType>
                    <xsd:sequence>
                        <xsd:element name="complex1" type="xsd:string"/>
                    </xsd:sequence>
                </xsd:complexType>
            </xsd:element>
        </element>
    </config>
    <pd:inputBindings>
        <mapComplex>
            <complex1>
                <xsl:value-of select="1"/>
            </complex1>
        </mapComplex>
    </pd:inputBindings>
</pd:activity>
<pd:activity name="MapElement">
    <config>
        <element>
            <xsd:element name="mapElement" type="xsd:string"/>
        </element>
    </config>
    <pd:inputBindings>
        <mapElement>
            <xsl:value-of select="1"/>
        </mapElement>
    </pd:inputBindings>
</pd:activity>
</pd:ProcessDefinition>

我正在使用以下代码来查找文件中的任何复杂元素是否具有名称空间前缀为xs的后代,即它们属于名称空间http://www.w3.org/2001/XMLSchema

String expression = "/ProcessDefinition/activity|//group/activity|/ProcessDefinition/starter";
NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(
            dDoc, XPathConstants.NODESET);
NodeListIterator iter = new NodeListIterator(nodeList);
while(iter.hasNext()) {
    Node nNode = iter.next();
    Element elem = (Element) nNode;
    String aName = elem.getAttribute("name");
    String ns = "http://www.w3.org/2001/XMLSchema";
    String schemaExpr = "//*[namespace-uri() = '"+ns+"']";
    NodeList nN = (NodeList) xPath.compile(schemaExpr).evaluate(nNode, XPathConstants.NODESET);
    System.out.println("##### NodeList: " + nN.getLength());
}

但是,代码始终将NodeList nN的大小返回为'0'。我在这里想念什么?

1 个答案:

答案 0 :(得分:0)

在XPath中,无限定名称与没有名称空间的元素匹配。因此/ProcessDefinition与您的源文档中的<pd:ProcessDefinition>不匹配。

最简单的解决方法是使用XSLT 2.0+处理器(例如Saxon),然后(1)在静态上下文中设置defaultXPathNamespace或(2)使用/*:ProcessDefinition/*:activity形式的步骤。

如果要坚持使用XPath 1.0,可以编写/pd:ProcessDefinition/pd:activity形式的表达式,并设置一个可识别前缀“ pd”的名称空间上下文。或者您可以使用/*[local-name()='ProcessDefinition']/*[local-name()='activity']/...

的形式编写表达式