harshit
harshit

Reputation: 3846

XPath expression not functioning

I have the following XML:

<thoughts>
    <thought>
        <id>1</id>
        <category>Leadership</category>
        <what>sometext</what>            
        <who>sometext</who>
    </thought>
    <thought>
        <id>2</id>
        <category>Leadership</category>
        <what>sometext</what>            
        <who>sometext</who>
    </thought>
    ... 100s of category Leadership
    <thought>
        <id>1</id>
        <category>Love</category>
        <what>sometext</what>            
        <who>sometext</who>
    </thought>
    <thought>
        <id>2</id>
        <category>Love</category>
        <what>sometext</what>            
        <who>sometext</who>
    </thought>
    ... 100s of category Love

    ... and so on up to about ten categories
</thoughts>

I want to select a thought(what) for a given id and category. I am doing this in Java. I tried the following:

"/thought[id='1']/thought[category='Love']/what/text()"

Java:

XPathFactory factory = XPathFactory.newInstance();
XPath xPath = factory.newXPath();
XPathExpression expr1 = xPath.compile("/thought[id='1']/thought[category='Love']/what/text()");
Object result1 = expr1.evaluate(doc, XPathConstants.NODESET);
NodeList nodes1 = (NodeList) result1;

I have also tried following XPathExpressions:

/thoughts/thought[id='1']/thought[category=`Love`]/what/text()

I am new to XML and XPath.

Upvotes: 2

Views: 121

Answers (2)

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243449

Use:

/*/thought[id = '1' and category = 'Love']/what

This selects any what element that is a child of a thought element, that has an id child with string value "1" and that has a category child with string value "Love", and that (the thought element) is a child of the top element of the XML document.

In case you need the text node children of the element(s) selected above, use:

/*/thought[id = '1' and category = 'Love']/what/text()

In case you need just the string value of the (first of) the above text node(s), use:

string(/*/thought[id = '1' and category = 'Love']/what)

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="/*/thought[id = '1' and category = 'Love']/what"/>
============
     <xsl:copy-of select="/*/thought[id = '1' and category = 'Love']/what/text()"/>
============
     <xsl:copy-of select="string(/*/thought[id = '1' and category = 'Love']/what)"/>
 </xsl:template>
</xsl:stylesheet>

When this transformation is applied on the following XML document (the provided one with distinct value for the wanted node):

<thoughts>
    <thought>
        <id>1</id>
        <category>Leadership</category>
        <what>sometext</what>
        <who>sometext</who>
    </thought>
    <thought>
        <id>2</id>
        <category>Leadership</category>
        <what>sometext</what>
        <who>sometext</who>
    </thought>
    ... 100's of with category Leadership     
    <thought>
        <id>1</id>
        <category>Love</category>
        <what>some Love text 1</what>
        <who>sometext</who>
    </thought>
    <thought>
        <id>2</id>
        <category>Love</category>
        <what>sometext</what>
        <who>sometext</who>
    </thought>
         ... 100's of with category Love
         ... and so on up to about ten categories 
</thoughts>

the three XPath expressions are evaluated and the results of these evaluations are copied to the output, separated visually by a handy delimiter:

<what>some Love text 1</what>
============
     some Love text 1
============
     some Love text 1

Update:

In a comment the OP has added the requirement that not only what, but also who should be selected.

Here are the corresponding new XPath expressions for this case:

/*/thought[id = '1' and category = 'Love']/*[self::what or self::who]

/*/thought[id = '1' and category = 'Love']/*[self::what or self::who]/text()

Upvotes: 1

Jiri Kremser
Jiri Kremser

Reputation: 12837

I would suggest following XPath xpression:

/thoughts/thought[id='1' and category='Love']/what/text()

I can recommend this tutorial

Upvotes: 0

Related Questions