XMLStarlet은 XPath 표현식에서 변수를 사용합니다.

XMLStarlet은 XPath 표현식에서 변수를 사용합니다.

나는 다음 명령을 가지고 있습니다 :

find . -iname '*.xml' | xargs xmlstarlet sel -N z="http://abc.com/article/1.0/" \\
--var zgtag="SuperTag" -t -m "/z:profile-extension" -i "//z:tag='$zgtag'" \\
-n -f -o "," -v "count(//z:zgContextsAnonymTotal[z:tag='$zgtag'])" -o "," \\
-v "//z:zgContextsAnonymTotal/z:tag[.='$zgtag']/@z:timestamp" -o "," \\ 
-v  "count(//z:zgContextsREGTotal[z:tag='$zgtag'])" -o "," \\
-v "//z:zgContextsREGTotal/z:tag[.='$zgtag']/@z:timestamp" -o "," \\
-v "count(//z:zgContextsPremiumTotal[z:tag='$zgtag'])" -o "," \\
-v "//z:zgContextsPremiumTotal/z:tag[.='$zgtag']/@z:timestamp" | grep -v ^$

명령어 버전에 변수가 없어서( $zgtag표시 결과를 사용하지 않고 같은 값을 반복해서) 동작하지 않습니다. 무엇이 문제일까요?

지금까지 조사한 내용은 다음과 같습니다.

  • --var zgtag="'SuperTag'"작은 따옴표가 없으면 xmlstarlet 컴파일된 XSLT가 다음과 같은 변수 선언을 생성하기 때문일 것입니다 . <xsl:variable select="SuperTag" name="zgtag"/>이것은 분명히 잘못된 것입니다. 작은 따옴표가 없습니다!
  • xmlstarlet 컴파일된 XSLT에서 변수가 올바르게 삽입되지 않은 것을 볼 수 있습니다. 예를 들면 다음과 같습니다.
<xsl:choose>
  <xsl:when test="//z:tag=''">

그런 다음 이 버전을 사용했습니다. --var zgtag="'SuperTag'" -m "/z:profile-extension" -i '//z:tag=$zgtag'이제 올바르게 컴파일된 xmlstarlet의 XSLT 디버그 출력을 얻습니다.

  <xsl:template match="/">
    <xsl:variable select="'SuperTag'" name="zgtag"/>
    <xsl:for-each select="/z:profile-extension">
      <xsl:choose>
        <xsl:when test="//z:tag=$zgtag">

그러나 출력은 여전히 ​​비어 있으며, 변수가 없는 동일한 스크립트( SuperTag스크립트를 여러 번 직접 삽입)는 정상적으로 작동합니다. 따라서 이 var 스타일 명령에 뭔가 문제가 있는 것 같습니다.

따라서 정의된 변수를 올바르게 삽입하고 사용하는 방법에 대한 도움을 환영합니다. 정의는 문제가 아니며 문제는 xmlstarlet 명령에서 변수를 사용하는 것입니다.

답변1

표현식의 단순화된 부분(네임스페이스 없음 등)을 살펴보겠습니다.

xmlstarlet sel --var zgtag="SuperTag" -t -m "/profile-extension" -i "//tag='$zgtag'"

zgtag로 참조되는 XPath 변수를 선언했습니다 $zgtag. 그러나 //tag='$zgtag'쉘이 구문 분석할 수 있도록 표현식을 큰따옴표 안에 넣었습니다 . 이 과정에서 변수를 평가하고 변수가 $zgtag아직 설정되지 않았다는 것을 알고 있습니다 . 그래서 당신은 이것을 얻습니다 :

xmlstarlet sel --var zgtag="SuperTag" -t -m "/profile-extension" -i "//tag=''"

그런 다음 명령을 실행하십시오. 분명히 원하는 대로 수행되지 않습니다.

항상 그렇듯이 해결책은 작은따옴표를 사용하여 셸에서 표현식을 보호하는 것입니다. (그리고 XPath에서 예상하지 않는 내부 작은따옴표를 사용할 때 제거하십시오)

xmlstarlet sel --var zgtag='"SuperTag"' -t -m "/profile-extension" -i '//tag=$zgtag'

일반적으로 셸에서 구문 분석할 필요가 없는 문자열은 작은따옴표를 사용하고, 그렇지 않으면 큰따옴표를 사용합니다. 바라보다셸에서 "...", '...', $'...' 및 $"..." 따옴표의 차이점은 무엇입니까?


작업된 예. 결과를 확인하기 위한 유효한 입력이나 예상 출력이 없기 때문에 사용자의 명령에 대해 애플리케이션을 테스트할 수 없습니다. 대신에 나는 이렇게 제안합니다.

cat >xml <<'EOF'
<?xml version="1.0"?>
<outer>
  <inner x="a">Element A text</inner>
  <inner x="b">Element B text</inner>
</outer>
EOF

xmlstarlet sel -t --var e='"b"' -v '//inner[@x=$e]' -n <xml

Element B text

관련 정보