Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XML element has namespace, my XPATH does not work

I was given the following XML:

<root>
  <items>
    <item>
      <title>Item</title>
      <details>
        <data xmlns="http://some_url">
          <length>10</length>
          <weight>1.2</weight>
        </data>
      </details>
    </item>
  </items>
</root>

Following XPath does not work meaning nothing is printed like the "data" element does not exists:

/root/items/item/details/data

But when I remove "xmlns" namespace attribute of "data" element it's content is printed. How should the xpath expression look like to work without deleting "xmlns" namespace attribute of "data" element?

I'm using SAXON and XSL 1.0.

like image 768
Vojtech Avatar asked Jun 11 '12 13:06

Vojtech


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 the correct way of declaring XML namespace?

XML Namespaces - The xmlns Attribute When using prefixes in XML, a namespace for the prefix must be defined. The namespace can be defined by an xmlns attribute in the start tag of an element. The namespace declaration has the following syntax. xmlns:prefix="URI".


1 Answers

This is one of the most FAQ in XPath / XSLT:

XPath interprets an unprefixed element name as belonging to "no namespace" and this is the reason elements with unprefixed names belonging to a default (nonempty) namespace aren't selected when only their unprefixed name is specified as a node-test in an XPath expression.

The solution is either:

  1. Create a namespace binding where a prefix (say "x") is associated with the default namespace, then specify x:elementName instead of elementName.

  2. Use long, ugly and unreliable expressions like: *[name() = 'elementName']

Here is an XSLT transformation using the above method1. :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:a="http://some_url">
 <xsl:output method="text"/>

 <xsl:template match="/">
  <xsl:value-of select=
  "/root/items/item/details/a:data/a:weight"/>
 </xsl:template>
</xsl:stylesheet>

When this transformation is applied (using Saxon 6.5.4 or any other compliant XSLT 1.0 processor) on the provided XML document:

<root>
    <items>
        <item>
            <title>Item</title>
            <details>
                <data xmlns="http://some_url">
                    <length>10</length>
                    <weight>1.2</weight>
                </data>
            </details>
        </item>
    </items>
</root>

The correct/wanted node is selected and its string value is copied to the output:

1.2
like image 106
Dimitre Novatchev Avatar answered Sep 19 '22 13:09

Dimitre Novatchev