2010-09-27 85 views
7

我想使用xpath表达式来选择一个xml文档中定义了不同名称空间的节点集。运行与名称空间的xpath查询问题

的XML看起来是这样的:

<?POSTEN SND="SE00317644000" REC="5566420989" MSGTYPE="EPIX"?> 
<ns:Msg xmlns:ns="http://www.noventus.se/epix1/genericheader.xsd"> 
    <GenericHeader> 
    <SubsysId>1</SubsysId> 
    <SubsysType>30003</SubsysType> 
    <SendDateTime>2009-08-13T14:28:15</SendDateTime> 
    </GenericHeader> 
    <m:OrderStatus xmlns:m="http://www.noventus.se/epix1/orderstatus.xsd"> 
    <Header> 
     <OrderSystemId>Soda SE</OrderSystemId> 
     <OrderNo>20090811</OrderNo> 
     <Status>0</Status> 
    </Header> 
    <Lines>... 

我要选择具有“OrderStatus”孩子,所以我想用下面的XPath表达式只是“消息” -nodes:/消息[计('OrderStatus')> 0]但这不起作用,因为我收到一条错误消息:“名称空间管理器或XsltContext需要,该查询具有前缀,变量或用户定义的函数”。所以我想我想用一个看起来像这样的表达式:/ * [local-name()='Msg'] [count('OrderStatus')> 0]但这似乎并不工作.. 有任何想法吗?

BR,

安德烈亚斯

回答

10

我想请使用以下XPath表达式 :

/Msg[count('OrderStatus')[ 0] 

但因为我得到的这不会工作错误消息说:“命名空间 Manager或XsltContext需要。

这是一个常见问题。

在XPath中,一个前缀不变的名称总是被认为属于“no namespace”。

但是,您要选择的元素实际上位于"http://www.noventus.se/epix1/genericheader.xsd" 命名空间中。

你有两种可能的方式来写你的XPath表达式

  1. 使用主导语言的设施,以前缀所有不同的命名空间,以从表达式名称属于关联。你没有在这个具体案例中表明什么是主机语言,所以我无法帮助你。一个C#的例子可以发现here

如果您有相关的前缀"xxx"命名空间"http://www.noventus.se/epix1/genericheader.xsd"和前缀"yyy"命名空间"http://www.noventus.se/epix1/orderstatus.xsd",那么你的表达式可以写成:

/xxx:Msg[yyy:OrderStatus]

:2:如果你不”不想使用任何前缀,仍然可以构建XPath表达式,但它不会太可读:

/*[local-name() = 'Msg' and *[local-name() = 'OrderStatus']]

最后,不要注意

  1. 为了测试一个元素是否x有一个孩子y没有必要来测试正面count(y)只需使用x[y]

  2. Xpath的位置是基于1。这意味着NodeSetExpression[0]从不选择一个节点。你想要:NodeSetExpression[1]