Command-Line Tools for XML

For shell scripts and quick checks, five tools on this machine answer the same question (titles of books over $30). xmlstarlet 1.6.1 comes from sudo apt install xmlstarlet:

cli.sh: one XPath question, five command-line toolsShell
q='//book[supply/price > 30]/title'
echo "xmllint:    $(xmllint --xpath "$q/text()" booknest-catalog.xml)"
echo "xmlstarlet: $(xmlstarlet sel -t -v "$q" booknest-catalog.xml)"
echo "Saxon:      $(xquery -s:booknest-catalog.xml -qs:"$q/string()")"
echo "BaseX:      $(basex -i booknest-catalog.xml "$q/string()")"
yqq='.catalog.book[] | select((.supply.price."+content" | to_number) > 30) | .title'
echo "yq:         $(yq -p xml -o yaml "$yqq" booknest-catalog.xml)"
Output
xmllint:    Patterns of the Deep Web
xmlstarlet: Patterns of the Deep Web
Saxon:      "Patterns of the Deep Web"
BaseX:      Patterns of the Deep Web
yq:         Patterns of the Deep Web
Command-line XML tools
Tool Language level Best for
xmllint 3,427 (libxml2 3,427 ) XPath 1.0 Well-formedness, DTD/XSD/RNG checks
xmlstarlet XPath 1.0, XSLT 1.0 Editing and selecting in scripts
Saxon 726,956 (xquery, xslt3) XPath/XQuery 3.1, XSLT 3.0 Real transformations
BaseX 693,830 XQuery 3.1 + Update, Full Text Repeated queries, databases
yq 16,045 (mikefarah) jq-like paths Mixed XML, YAML, JSON jobs

yq turns XML into a YAML-like tree, so an element with attributes keeps its text in +content, and all values are strings: comparing them with a number failed ("!!str not yet supported for comparison") until to_number.