XPATH: select a subset of the xml file
In my case, I have:
<booklist> <book id="1"> </book> <book id="2"> </book> <book id="3"> </book> ...... </booklist> How can I just go back:
<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 a document element. Thanks
Instead of picking the item you need , try eliminating the items you don't need .
If you use XPATH , this will select all elements except book elements that @id not equal to 1 (i.e. <booklist><book id="1" /></booklist> ).
//*[not(self::book[@id!='1'])] If you want to use the XSLT solution , this stylesheet has an empty template that matches all <book> elements that do not have @id="1" , which prevents them from being copied to the output.
Everything else (the document node <booklist> and <book id="1"> ) will match the identity template that 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> How can I just go back:
< booklist > < book id=1 > < /book > < /booklist >
XPath is a query language. Evaluating an XPath expression cannot change the structure of an XML document.
This is why the answer: No, with XPath this is not possible!
Whenever you want to convert an XML document (this is the case in this case), probably the best solution is to use XSLT, a language that was developed specifically for processing and transforming tree 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 conversion is applied to the provided XML file, the required, correct result is obtained :
<booklist> <book id="1"/> </booklist>