5

In my case, I have:

<booklist>
  <book id="1">
  </book>

  <book id="2">
  </book>

  <book id="3">
  </book>

  ......

</booklist>

How can i just return:

<booklist>
  <book id="1">
  </book>
</booklist>

if I use /booklist/book[@id=1], I can only get

<book id="1">
</book>

But I also need the document element. Thanks

1
  • Good Question (+1). See my answer for a complete solution. Commented May 30, 2010 at 19:30

3 Answers 3

6

Rather than selecting the element that you do want, try excluding the elements that you don't want.

If you are just using XPATH, this will select all of the elements except for the book elements who's @id is not equal to 1 (i.e. <booklist><book id="1" /></booklist>).

//*[not(self::book[@id!='1'])]

If you want an XSLT solution, this stylesheet has an empty template that matches all of the <book> elements that do not have @id="1", which prevents them from being copied into the output.

Everything else (document node <booklist> and <book id="1">) will match the identity template, which copies forward.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <!--Empty template to prevent book elements
        that do not have @id="1" from being
        copied into the output -->
    <xsl:template match="book[@id!='1']" />

    <!--identity template to copy all nodes and attributes to output -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>
Sign up to request clarification or add additional context in comments.

1 Comment

I am facing a problem in xpath transformation in xml signatures in java. The xpath tranformation does not seem to take place. Can you please have a look at this question - stackoverflow.com/questions/10698287/…
3

How can i just return:

< booklist >
< book id=1 >
< /book >
< /booklist >

XPath is a query language. Evaluating an XPath expression cannot change the structure of the XML document.

This is why the answer is: No, with XPath this is not possible!

Whenever you want to transform an XML document (which is exactly the case here), the probably best solution is to use XSLT -- a language which was designed especially for processing and transforming tree-structured data.

Here is a very simple XSLT solution:

<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="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="book[not(@id=1)]"/>
</xsl:stylesheet>

When this transformation is applied to the provided XML file, the wanted, correct result is produced:

<booklist>
   <book id="1"/>
</booklist>

Comments

2

When you try to select a sub-element, only this will be returned.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.