tags:

views:

17

answers:

1

Hi,

I'm trying to use an xpath expression to select a node-set in an xml document with different namespaces defined.

The xml looks something like this:

<?POSTEN SND="SE00317644000" REC="5566420989" MSGTYPE="EPIX"?>
<ns:Msg xmlns:ns="http://www.noventus.se/epix1/genericheader.xsd"&gt;
  <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"&gt;
    <Header>
      <OrderSystemId>Soda SE</OrderSystemId>
      <OrderNo>20090811</OrderNo>
      <Status>0</Status>
    </Header>
    <Lines>...

I want to select only "Msg"-nodes that has the "OrderStatus" child and therefore I want to use the following xpath expression: /Msg[count('OrderStatus') > 0] but this won't work since I get an error message saying: "Namespace Manager or XsltContext needed. This query has a prefix, variable, or user-defined function".

So I think I want to use an expression that looks something like this: /*[local-name()='Msg'][count('OrderStatus') > 0] but that doesn't seem to work.. any ideas?

Br,

Andreas

A: 

I want to use the following xpath expression:

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

but this won't work since I get an error message saying: "Namespace Manager or XsltContext needed.

This is a FAQ.

In XPath a unprefixed name is always considered to belong in "no namespace".

However, the elements you want to select are in fact in the "http://www.noventus.se/epix1/genericheader.xsd" namespace.

You have two possible ways to write your XPath expression:

  1. Use the facilities of the hosting language to associate prefixes to all different namespaces to which names from the expression belong. You haven't indicated what is the hosting language in this concrete case, so I can't help you with this. A C# example can be found here.

If you have associated the prefix "xxx" to the namespace "http://www.noventus.se/epix1/genericheader.xsd" and the prefix "yyy" to the namespace "http://www.noventus.se/epix1/orderstatus.xsd", then your Expression can be written as:

/xxx:Msg[yyy:OrderStatus]

:2: If you don't want to use any prefixes at all, an XPath expression can still be constructed, however it will not be too readable:

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

Finally, do note:

  1. In order to test if an element x has a child y it isn't necessary to test for a positive count(y). Just use: x[y]

  2. Xpath positions are 1-based. This means that NodeSetExpression[0] never selects a node. You want: NodeSetExpression[1]

Dimitre Novatchev