......

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

+4
source share
3 answers

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> 
+6
source

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> 
+3
source

When you try to select a subitem, only this returns.

+2
source

Source: https://habr.com/ru/post/1311291/


All Articles