Henry
Henry

Reputation: 384

xpath based on attribute and value

I need to process same xml, below is partial of it:

<response>
<dat id="1">
    <b>
        <i>1</i>
    </b>
    <ds>
        <d>
            <t>2012-12-21</t>

what xpath I need to use to select the element "d", which has a parent-parent element "dat" with attribute id="1" and has a child element "t" with value of 2012-12-21?

It is in C#, the application grabs this xml from internet and loads it into XmlDocument. Currently I am doing multiple steps: find note "dat", then find "t" under "dat", then go to parent node "d". I am hoping to have xpath to replace the above multiple steps.

I've tried this xpath: //dat[@id="1"]/ds/d[t="2012-12-21"], but return null node

Thanks.

EDIT: See below for Dimitre Novatchev's solution.

btw: //dat[@id="1"]/ds/d[t="2012-12-21"] worked as well, not sure what happened when I did the test.

Upvotes: 1

Views: 778

Answers (1)

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243599

Use:

//dat[@id = 1]/*/d[t[. = '2012-12-21']]

This selects all d elements that have a t child, whose string value is the string '2012-12-21',

and whose grand-parent is a dat that has an id attribute with numeric value of 1.

In case you want to select just one (say the first) of all such elements, use:

(//dat[@id = 1]/*/d[t[. = '2012-12-21']])[1]

XSLT - based verification:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/">
  <xsl:copy-of select="//dat[@id = 1]/*/d[t[. = '2012-12-21']]"/>
 </xsl:template>
</xsl:stylesheet>

When this transformation is applied on the (finished) provided XML document:

<response>
    <dat id="1">
        <b>
            <i>1</i>
        </b>
        <ds>
            <d>
                <t>2012-12-21</t>
            </d>
        </ds>
    </dat>
</response>

the above XPath expression is evaluated and the result of this evaluation (the selected node(s) ) is copied to the output:

<d>
   <t>2012-12-21</t>
</d>

Upvotes: 1

Related Questions