Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Namespace agnostic XPath query with element content

The namespace agnostic syntax I've seen around is confusing me.

Say I have:

<root>
  <parent attribute="A">A<child>A</child></parent>
  <parent attribute="B">B<child>B</child></parent>
</root>

So far I see how:

/root/parent/child/text()

translates to:

/*[local-name()='root']/*[local-name()='parent']/*[local-name()='child']/text()

but i'm struggling with things like this:

/root/parent[@attribute="A"]/child/text()

or:

/root/parent[text()="B"]/child/text()

or:

/root/parent[1]/child/text()

How do these translate?

Thanks,

EDIT: One More :-)

<root>
        <parent>
            <childName>serverName</childName>
            <childValue>MyServer</childValue>
        </parent>
        <parent>
            <childName>ServerLocation</childName>
            <childValue>Somewhere</childValue>
         </parent>
</root>

How does this translate?

/root/parent[childName="serverName"]/childValue/text()
like image 336
Andy Arismendi Avatar asked Feb 10 '11 04:02

Andy Arismendi


People also ask

How to use XPath with 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 to specify namespace in XPath expression?

Within RUEI, all namespaces used in your XPath queries must be explicitly defined. If a namespace is used in a query, but is not defined, it will not work. To define a namespace, do the following: Select Configuration, then General, Advanced settings, and then XPath namespaces.

What is namespace node in XPath?

Introduction to XPath namespace. In an XML document, namespaces are used to provide uniquely named components and attributes. A namespace is made up of two parts: a prefix and a URL. This indicates the location of a document that defines the namespace in question.


2 Answers

The namespace agnostic syntax I've seen around is confusing me.

First, I would advise you not to use this syntax, especially if it is confusing. It can also result in errors -- see the end of my answer for details.

The standard way to specify in an XPath expression names that are in a namespace is to register a namespace with your XPath engine (see the respective, vendor-specific documentation) and then to use the prefix bound to the registered namespace (say "x") with names like x:someName

There are plenty of good answers on this topic -- jus t use one of them.

Now, if due to some reason you still decide to use the confusing syntax, then:

but i'm struggling with things like this:

/root/parent[@attribute="A"]/child/text()

Use:

/*[local-name()='root']/*[local-name()='parent' and @attribute='A']

then:

or:

/root/parent[text()="B"]/child/text()

Use:

/*[local-name()='root']/*[local-name()='parent' and text()='B']
                                    /*[local-name()='child']/text()

then:

or:

/root/parent[1]/child/text()

Use:

/*[local-name()='root']/*[local-name()='parent'][1]
                                 /*[local-name()='child']/text()

then:

One More :-)

<root>
  <parent>
      <childName>serverName</childName>
      <childValue>MyServer</childValue>
  </parent>
  <parent>
      <childName>ServerLocation</childName>
      <childValue>Somewhere</childValue>
  </parent>
</root>

How does this translate?

/root/parent[childName="serverName"]/childValue/text()

Use:

/*[local-name()='root']
      /*[local-name()='parent'][*[local-name()='childName"]='serverName']
                                           /*[local-name()='childValue']/text()

Do note:

Such expressions may not select the wanted nodes if in the XML documents there are elements with the same local-name that belong to two different namespaces.

like image 70
Dimitre Novatchev Avatar answered Oct 28 '22 19:10

Dimitre Novatchev


I understand your question to mean, how do I make these XPath expressions namespace-agnostic? (It's not a special syntax, just a typical use of the local-name() function.)

/root/parent[@attribute="A"]/child/text()

would become

/*[local-name()='root']/*[local-name()='parent'][@attribute='A']/*[local-name()='child']/text()

(You could use double-quotes for the attribute value if you want, but that would make it harder to embed in XSLT or whatever your environment is.)

/root/parent[text()="B"]/child/text()

would become

/*[local-name()='root']/*[local-name()='parent'][text() = 'B']/*[local-name()='child']/text()

And

/root/parent[1]/child/text()

would become

/*[local-name()='root']/*[local-name()='parent'][1]/*[local-name()='child']/text()
like image 42
LarsH Avatar answered Oct 28 '22 19:10

LarsH