XPath结果为空字符串

时间:2011-08-26 13:11:11

标签: java xml xpath

以下是我的XML文件

<xyzevent xmlns="http://www.xyz.com/common/xyzevent/v1" xmlns:xsi="http://www.w3.org2001XMLSchema-instance">
<header>
 ----
</header>
<subscription xmlns="http://www.xyz.com/common/xyzevent/source/v1">
  <sender></sender>
  <receiver>
    <clientsubscription>
        <servicemap>nanna</servicemap>
    </clientsubscription>
  </receiver>
</subscription> 
</xyzevent>

当我从这个XML发布org.w3c.dom.Document并使用表达式

应用XPathExperssion时
/xyzevent/subscription/receiver/clientsubscription/servicemap/text()

结果为空字符串。表达式的问题可能是什么?

谢谢

4 个答案:

答案 0 :(得分:7)

那是因为您的XML文档使用了命名空间。 XPath真的很烦人的命名空间。要确认这一点,请从文档中删除两个xmlns=http://.../v1并再次运行未命名的无法验证的XML文件的XPath表达式。它会匹配。

当您的文档包含/xyzevent时,您的XPath表达式会尝试选择{http://.../v1}:xyzevent,这不是一回事。

有很多方法可以解决这个问题。正确的方法是设置NamespaceContext,这样您就可以在XPath表达式中使用prefix:localName表示法,并将前缀解析为正确的URI。 xerces docs还有一些elsewhere on StackOverflow,有一个简短的模糊。 ibm.com上有广泛的描述。

您的NamespaceContext将包含两个(或更多)映射:

{
    event => http://www.xyz.com/common/xyzevent/v1
    source => http://www.xyz.com/common/xyzevent/source/v1
}

您的XPath表达式可以变为/event:xyzevent/source:subscription/source:receiver/.../text()

作为讨厌的解决方法,您可以使用local-name()函数重写xpath表达式进行选择:

/*[local-name()='xyzevent']/*[local-name()='subscription'/ ...

在这种情况下,表达式匹配任何本地名称为xyzevent的元素,而不管名称空间URI。

答案 1 :(得分:2)

您的XML具有默认命名空间:xmlns="http://www.xyz.com/common/xyzevent/v1",因此您需要在XML / XPath引擎中定义它。

或者使用此XPath:

/*[local-name() = 'xyzevent']
    /*[local-name() = 'subscription']
        /*[local-name() = 'receiver']
            /*[local-name() = 'clientsubscription']
                /*[local-name() = 'servicemap']
                    /text()

答案 2 :(得分:1)

xyzevent是您的根元素,因此您只需使用"/subscription/receiver/clientsubscription/servicemap/text()"

答案 3 :(得分:1)

我在以下链接中评估了您的表达式:

http://www.whitebeam.org/library/guide/TechNotes/xpathtestbed.rhtm

看起来,它选择了“nanna”。