Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problem running xpath query with namespaces

Tags:

xpath

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

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

like image 825
Andreas Andersson Avatar asked Sep 27 '10 13:09

Andreas Andersson


People also ask

How does XPath handle namespace?

XPath queries are aware of namespaces in an XML document and can use namespace prefixes to qualify element and attribute names. Qualifying element and attribute names with a namespace prefix limits the nodes returned by an XPath query to only those nodes that belong to a specific namespace.

How do I find the XPath namespace?

There is no method to connect a namespace prefix to a namespace in XPath. The hosting library can provide these services. It is strongly advised that we take advantage of those features and create namespace prefixes that may be used to qualify XML element and attribute names as needed.

What is namespace node in XPath?

XPath defines a way to compute a string-value for each type of node. Some types of nodes also have names. XPath fully supports XML Namespaces. Thus, the name of a node is modeled as a pair consisting of a local part and a possibly null namespace URI; this is called an expanded-name.

What is the meaning of '/' in XPath?

0 votes. Single Slash “/” – Single slash is used to create Xpath with absolute path i.e. the xpath would be created to start selection from the document node/start node.


1 Answers

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]

like image 158
Dimitre Novatchev Avatar answered Sep 28 '22 17:09

Dimitre Novatchev