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
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>
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With