This week I needed to validate the number of entries in an XML file.
After a short Google search I came across xmllint
.
This handy little CLI tool looked like the perfect tool for this job, so I tried it out immediately.
Unfortunately it took me some time to figure out how I can use it with my XML file.
Here is why:
Counting XML entries in an XML file without a namespace is pretty straightforward.
Let’s assume our XML file has the following structure and we want to find the number of entries.
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<record>
<id>1</id>
<first_name>Dru</first_name>
<last_name>Greenway</last_name>
<email>dgreenway0@technorati.com</email>
<ip_address>168.235.172.238</ip_address>
</record>
<record>
<id>2</id>
<first_name>Agnesse</first_name>
<last_name>Janousek</last_name>
<email>ajanousek1@unblog.fr</email>
<ip_address>62.116.98.136</ip_address>
</record>
</dataset>
One can simply pass a xpath expression to xmllint
and make use of the count
function:
xmllint --xpath "count(//record)" example.xml
For more information on xpath syntax checkout: https://www.w3schools.com/xml/xpath_syntax.asp
In the example from above the result would be 2
.
Unfortunately my XML file looked a bit different since it had a default namespace defined.
If we change <dataset>
to <dataset xmlns="http://www.some-custom-namespace.org">
.
The same command:
xmllint --xpath "count(//record)" example.xml
returns 0
since the xpath expression does not match any element.
How can we solve this problem?
Option 1
Use the interactive shell:
xmllint --shell example_with_ns.xml
Set the namespace to the referenced namespace in your file, in our example:
setns x=http://www.some-custom-namespace.org
Execute xpath command:
xpath count(//x:record)
... prints 2
Note the x prefix!
This prefix must match the variable chosen in the setns
command.
Option 2
Make use of the local-name
function:
xmllint -xpath "count(//*[local-name()='record'])" example_with_ns.xml
... prints 2
Sources:
https://gist.github.com/bitsgalore/3e403b02f776f03444c0622cb3b08b56
https://stackoverflow.com/a/8266075/3533210
Photo credit:
Photo by Josh Appel on Unsplash
Top comments (0)