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

이는 두 개의 셸 변수를 사용하여 XML 파일을 쿼리합니다. 이 the_id변수에는 id필터링하려는 속성 값과 the_mediatype_prefix속성이 시작해야 하는 문자열도 포함되어 있습니다.media-type

xmlstarlet도구의 옵션을 사용하기 위해 두 개의 내부 변수를 만듭니다 --var. 이러한 값은 인코딩된 값이어야 하므로 주위에 작은따옴표를 삽입했습니다(이것은 약간 번거롭습니다. 이상적으로는 XPath 문자열을 올바르게 인코딩해야 하지만 쉘 변수를 표현식에 직접 삽입하는 것보다 낫습니다).

XPath 표현식은 합이 일치하는 각 노드의 속성을 선택합니다 href.itemidmedia-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

xmlstarletjqXPath 쿼리 대신 표현식을 사용한다는 점을 제외하면 이는 거의 동일한 코드입니다. 여기에서 유틸리티는 따옴표와 같은 불안정한 값이 포함된 경우에도 쉘 변수를 올바르게 인코딩해야 합니다(예제의 쉘 변수 값에 xmlstarlet잘못된 문자 시퀀스가 ​​포함된 경우 수동으로 인코딩해야 합니다).

답변2

여러 조건을 추가할 수 있습니다.

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

관련 정보