the_id='cover'
the_mediatype_prefix='image/'
xmlstarlet sel -t \
--var queryid="'$the_id'" \
--var typeprefix="'$the_mediatype_prefix'" \
-v '//item[@id = $queryid and starts-with(@media-type, $typeprefix)]/@href' \
-nl file.xml
This queries the XML file using two shell variables. The the_id
variable contains the id
attribute value that we are filtering with, while the_mediatype_prefix
contains the string that the media-type
attribute has to start with.
We create two internal variables for xmlstarlet
using the tool's --var
option. The values need to be encoded values, which is why I insert single quotes around them (this is a bit of a hack, ideally they should be properly encoded XPath strings, but it's marginally better than injecting shell variables directly into the expression).
The XPath expression select the href
attribute of each item
node that has the matching id
and media-type
.
Using xq
(an XML parser wrapper around jq
, the JSON parser) instead:
the_id='cover'
the_mediatype_prefix='image/'
xq -r \
--arg queryid "$the_id" \
--arg typeprefix "$the_mediatype_prefix" '
.. | .item? |
select(
."@id" == $queryid and
(."@media-type" | startswith($typeprefix))
)."@href"' file.xml
This is more or less identical to the xmlstarlet
code, apart from using a jq
expression instead of a XPath query. Here, the utility takes care of encoding your shell variables properly, even if they contain wonky values like quotes etc. (the shell variable values in the xmlstarlet
example would need to be encoded manually if they contain illegal character sequences).