2011-08-26 190 views
5

以下是我的XML文件XPath的结果空字符串

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

当我budila org.w3c.dom.Document中从该XML和应用XPathExperssion与表达

/xyzevent/subscription/receiver/clientsubscription/servicemap/text() 

结果空字符串。这个表达式有什么问题?

谢谢

回答

6

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

发生了什么是您的XPath表达式试图选择/xyzevent,当您的文档包含{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()

作为讨厌的解决方法,你可以重写你的XPath表达式使用local-name()功能选择:

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

在这种情况下,表达的,任何元素,它的本地名称是xyzevent无论空间URI相匹配。

+0

删除xmlns = http://.../v1后,我可以从这两个地方获得值。但是,你能否向我解释如何在我们在文档中同时创建名称空间值时创建NamespaceContext ... – Pokuri

+0

@Pokuri在'NamespaceContext'中注册两个单独的前缀,例如, 'event'和'source'都有适当的URI。您的XPath表达式将成为'/ event:xyzevent/source:subscription/source:receiver/...' – Barend

+0

但NamespaceContext需要一个namespaceURI和一个或多个前缀。那么如何将两个NamespaceContext传递给XPath.setNamespaceContext(namespaceContext);方法 – Pokuri

1

xyzevent是你的根元素,所以你只需要使用"/subscription/receiver/clientsubscription/servicemap/text()"

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