如何使用 xmlstarlet 查询标签的两个属性值?

如何使用 xmlstarlet 查询标签的两个属性值?

例子:- <item href="cover.jpeg" id="cover" media-type="image/jpeg"/>

我想选择 @id="cover" 和 media-type="image/*" 并检索 @href。

我当前的“解决方案”似乎是:- xmlstarlet sel -t -m "//_:item[@id='$opf_cover_name']" -v @href -o '|' -v @media-type -n file.xml,然后是围绕“|”进行一些极其混乱的分割输出的字符。

Does xmlstarlet have a substring function?
Version = 1.6.1
compiled against libxml2 2.9.4, linked with 20904
compiled against libxslt 1.1.29, linked with 10132

答案1

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

这使用两个 shell 变量查询 XML 文件。该the_id变量包含id我们要过滤的属性值,同时包含该属性必须开头的the_mediatype_prefix字符串。media-type

我们创建两个内部变量来xmlstarlet使用该工具的--var选项。这些值需要是编码值,这就是为什么我在它们周围插入单引号(这有点麻烦,理想情况下它们应该是正确编码的 XPath 字符串,但它比直接将 shell 变量注入表达式要好一些)。

XPath 表达式选择具有匹配和的href每个节点的属性。itemidmedia-type


使用xqXML 解析器包装器 around jq,JSON 解析器)改为:

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

xmlstarlet除了使用jq表达式而不是 XPath 查询之外,这与代码或多或少相同。在这里,该实用程序负责正确编码您的 shell 变量,即使它们包含引号等不稳定值(示例中的 shell 变量值xmlstarlet如果包含非法字符序列,则需要手动编码)。

答案2

您可以添加多个条件:

xmlstarlet sel -t -m "//item[@id='cover'][starts-with(@media-type,'image/')]" -v '@href' -nl file.xml

相关内容