Today I get to learn how to use xmllint properly. It does not seem to be well covered or explained. I plan to use a single language resource file to run my entire system. I have a mixture of bash scripts and php pages that must read from this language file.
Currently I am using the following format in my xml file en.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item id="index.php">
<label>LABEL</label>
<value>VALUE</value>
<description>DESCRIPTION</description>
</item>
<item id="config.php">
<label>LABEL</label>
<value>VALUE</value>
<description>DESCRIPTION</description>
</item>
</resources>
Now I need to start with a bash script line that should pull the data values from the xml file. For example I want to get the value of DESCRIPTION
from the index.php
item.
I was using
xmllint --xpath 'string(//description)' /path/en.xml
for a different layout which worked, but now that I am changing the layout of my xml file, I am lost as to how best to target a specific <item>
and then drill down to its child element in the bash script.
Can someone help with a xmllint --xpath
line to get this value please?
how best to target a specific and then drill down to its child element
The correct XPath expression to do this is:
/resources/item[@id="index.php"]/description/text()
In plain English: Start from the document node, to the document element resources
, on to its child item
, but only if the value of the id
attribute is "index.php", on to its child description
and retrieve its textual value.
I use xmllint to validate XML documents, but never for path expressions. In a bash shell (at least with Mac OS) there is an even simpler tool for evaluating XPath expressions, called "xpath":
$ xpath en.xml '/resources/item[@id="index.php"]/description/text()'
Then, the following result is obtained:
Found 1 nodes:
-- NODE --
DESCRIPTION
If you still prefer xmllint, use it in the following way:
$ xmllint --xpath '/resources/item[@id="index.php"]/description/text()' en.xml > result.txt
By default, --xpath
implies --noout
, which prevents xmllint from outputting anything. Redirect the output to a file.
$ cat result.txt
DESCRIPTION
My favorite is xmlstarlet because it seems to be more powerful than xmllint:
xmlstarlet sel -t -v '/resources/item[@id="index.php"]/description/text()' en.xml
I had the same problem a few minutes ago and saw this post.
After hacking a bit I found the following solution to extract the city:
(wget 'http://maps.googleapis.com/maps/api/geocode/xml?latlng=53.244921,-2.479539&sensor=true' -O dummy.xml -o /dev/null;xmllint --format --xpath '/GeocodeResponse/result[type = "postal_town"]/address_component[type = "postal_town"]/short_name/node()' dummy.xml)
You nee to specify the correct X-Path to get the desired XML-Tag and then return only the node value.