例:-
<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
これは2つのシェル変数を使用してXMLファイルを照会します。このthe_id
変数には、id
フィルタリングする属性の値と、the_mediatype_prefix
属性が開始する必要がある文字列も含まれています。media-type
xmlstarlet
ツールのオプションを使用するために2つの内部変数を作成します--var
。これらの値はエンコードされた値でなければならないので、周囲に一重引用符を挿入しました(これは少し面倒です。理想的にはXPath文字列を正しくエンコードする必要がありますが、シェル変数を式に直接挿入するよりも優れています)。
XPath式は、合計が一致する各ノードの属性を選択しますhref
。item
id
media-type
使用xq
(XMLパーサーラッパー 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クエリの代わりに式を使用することを除いて、これはほぼ同じコードです。ここで、ユーティリティは引用符などの不安定な値が含まれていてもシェル変数を正しくエンコードする必要があります(例のシェル変数値にxmlstarlet
無効な文字シーケンスが含まれている場合は手動でエンコードする必要があります)。
答え2
複数の条件を追加できます。
xmlstarlet sel -t -m "//item[@id='cover'][starts-with(@media-type,'image/')]" -v '@href' -nl file.xml