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).