16
votes

I am looking for a way to extract and print an element from my xml using xmlstarlet; for example if my xml is

<?xml version="1.0" encoding="ISO-8859-1"?>

<bookstore>

<book>
  <title lang="eng">Harry Potter</title>
  <price>29.99</price>
</book>

<book>
  <title lang="eng">Learning XML</title>
  <price>39.95</price>
</book>

</bookstore>

I would like to print out book element with price = 29.99 as:

<book>
  <title lang="eng">Harry Potter</title>
  <price>29.99</price>
</book>

I understand the xpath query to select such an element (/bookstore/book[price=29.99]) but I am not able to print/dump it on stdout. If I use the '-v' option and use -v (.) I don't get the output as I want (with all the tags in it) I just get the text values. There ought to be a way to simply dump selected element as it is, and that's what I am looking for.

Thanks in anticipation.

1

1 Answers

19
votes

Using the "-c" (copy) option, should achieve what you're after:

xmlstarlet sel -t -c "/bookstore/book[price=29.99]" books.xml

<book>
  <title lang="eng">Harry Potter</title>
  <price>29.99</price>
</book>

You can watch the XSLT generated internally in xmlstarlet by adding the global "-C" switch after "sel". This shows how the copy option results in an xslt copy-of construct:

...
<xsl:template name="t1">
  <xsl:copy-of select="/bookstore/book[price=29.99]"/>
</xsl:template>
...

This results in namespace nodes, child nodes, and attributes nodes being included, cf. the XSLT spec (see w3schools summary).