Programing

Bash에서 XML을 구문 분석하는 방법은 무엇입니까?

lottogame 2020. 7. 3. 18:41
반응형

Bash에서 XML을 구문 분석하는 방법은 무엇입니까?


이상적으로, 내가 할 수있는 일은 다음과 같습니다.

cat xhtmlfile.xhtml |
getElementViaXPath --path='/html/head/title' |
sed -e 's%(^<title>|</title>$)%%g' > titleOfXHTMLPage.txt

이것은 실제로 Yuzem의 대답에 대한 설명 일뿐 이지만 다른 사람에게 많은 편집을해야한다고 생각하지 않았으며 주석은 형식을 허용하지 않습니다.

rdom () { local IFS=\> ; read -d \< E C ;}

"rdom"대신 "read_dom"이라고 부르고 약간 간격을두고 더 긴 변수를 사용하십시오.

read_dom () {
    local IFS=\>
    read -d \< ENTITY CONTENT
}

이제 read_dom이라는 함수를 정의합니다. 첫 번째 행은 IFS (입력 필드 구분 기호)를이 함수의 로컬로 만들고>로 변경합니다. 즉, 공간, 탭 또는 줄 바꿈에서 자동으로 분할되는 대신 데이터를 읽을 때 '>'에서 분할됩니다. 다음 줄은 stdin에서 입력을 읽도록 지시하고 개행에서 멈추지 말고 '<'문자 (deliminate 플래그의 경우 -d)가 표시되면 중지하십시오. 읽은 내용은 IFS를 사용하여 분할되고 변수 ENTITY 및 CONTENT에 지정됩니다. 따라서 다음을 수행하십시오.

<tag>value</tag>

read_dom'<'가 첫 번째 문자이므로 빈 문자열 얻는 첫 번째 호출 입니다. '>'문자가 없기 때문에 IFS에 의해 ''로 분할됩니다. 그런 다음 읽기는 빈 문자열을 두 변수 모두에 할당합니다. 두 번째 호출은 문자열 'tag> value'를 가져옵니다. 그런 다음 IFS에 의해 두 필드 'tag'와 'value'로 나뉩니다. 읽기는 다음과 같은 변수를 할당합니다 ENTITY=tagCONTENT=value. 세 번째 호출은 문자열 '/ tag>'를 가져옵니다. 그것은 IFS에 의해 '/ tag'와 ''의 두 필드로 나뉩니다. 읽기는 다음과 같은 변수를 할당합니다 ENTITY=/tagCONTENT=. 파일 끝에 도달했기 때문에 네 번째 호출은 0이 아닌 상태를 반환합니다.

이제 그의 while 루프는 위와 일치하도록 약간 정리했습니다.

while read_dom; do
    if [[ $ENTITY = "title" ]]; then
        echo $CONTENT
        exit
    fi
done < xhtmlfile.xhtml > titleOfXHTMLPage.txt

첫 번째 줄은 "read_dom 함수가 0 상태를 반환하는 동안 다음을 수행합니다."라고 말합니다. 두 번째 줄은 방금 본 엔터티가 "title"인지 확인합니다. 다음 줄은 태그의 내용을 에코합니다. 네 줄이 나옵니다. 제목 엔터티가 아닌 경우 루프는 여섯 번째 줄에서 반복됩니다. "xhtmlfile.xhtml"을 표준 입력 ( read_dom함수의 경우)으로 리디렉션하고 표준 출력을 "titleOfXHTMLPage.txt"(루프의 앞부분에서 나오는 에코)로 리디렉션합니다.

이제 다음에 대해 (S3에 버킷을 나열하여 얻는 것과 비슷한) 다음을 제공합니다 input.xml.

<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  <Name>sth-items</Name>
  <IsTruncated>false</IsTruncated>
  <Contents>
    <Key>item-apple-iso@2x.png</Key>
    <LastModified>2011-07-25T22:23:04.000Z</LastModified>
    <ETag>&quot;0032a28286680abee71aed5d059c6a09&quot;</ETag>
    <Size>1785</Size>
    <StorageClass>STANDARD</StorageClass>
  </Contents>
</ListBucketResult>

그리고 다음 루프 :

while read_dom; do
    echo "$ENTITY => $CONTENT"
done < input.xml

당신은 얻을 것이다 :

 => 
ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/" => 
Name => sth-items
/Name => 
IsTruncated => false
/IsTruncated => 
Contents => 
Key => item-apple-iso@2x.png
/Key => 
LastModified => 2011-07-25T22:23:04.000Z
/LastModified => 
ETag => &quot;0032a28286680abee71aed5d059c6a09&quot;
/ETag => 
Size => 1785
/Size => 
StorageClass => STANDARD
/StorageClass => 
/Contents => 

따라서 whileYuzem과 같은 루프를 작성하면

while read_dom; do
    if [[ $ENTITY = "Key" ]] ; then
        echo $CONTENT
    fi
done < input.xml

S3 버킷에있는 모든 파일 목록이 표시됩니다.

편집 어떤 이유로 든 local IFS=\>당신을 위해 작동하지 않고 전역으로 설정하면 다음과 같이 기능 끝에서 재설정해야합니다.

read_dom () {
    ORIGINAL_IFS=$IFS
    IFS=\>
    read -d \< ENTITY CONTENT
    IFS=$ORIGINAL_IFS
}

그렇지 않으면 스크립트에서 나중에 행을 분할하면 엉망이됩니다.

편집 2 속성 이름 / 값 쌍을 분리하려면 다음 read_dom()과 같이 기능을 보강 할 수 있습니다 .

read_dom () {
    local IFS=\>
    read -d \< ENTITY CONTENT
    local ret=$?
    TAG_NAME=${ENTITY%% *}
    ATTRIBUTES=${ENTITY#* }
    return $ret
}

그런 다음 함수를 작성하여 원하는 데이터를 구문 분석하고 얻으십시오.

parse_dom () {
    if [[ $TAG_NAME = "foo" ]] ; then
        eval local $ATTRIBUTES
        echo "foo size is: $size"
    elif [[ $TAG_NAME = "bar" ]] ; then
        eval local $ATTRIBUTES
        echo "bar type is: $type"
    fi
}

그런 다음 read_dom전화 하는 동안 parse_dom:

while read_dom; do
    parse_dom
done

그런 다음 다음 예제 마크 업이 제공됩니다.

<example>
  <bar size="bar_size" type="metal">bars content</bar>
  <foo size="1789" type="unknown">foos content</foo>
</example>

이 출력을 가져와야합니다.

$ cat example.xml | ./bash_xml.sh 
bar type is: metal
foo size is: 1789

EDIT 3 다른 사용자 는 FreeBSD에서 문제가 있다고 말했으며 read에서 종료 상태를 저장하고 read_dom의 끝에서 그것을 반환하도록 제안했습니다.

read_dom () {
    local IFS=\>
    read -d \< ENTITY CONTENT
    local RET=$?
    TAG_NAME=${ENTITY%% *}
    ATTRIBUTES=${ENTITY#* }
    return $RET
}

왜 작동하지 않는지 알 수 없습니다.


bash 만 사용하면 매우 쉽게 할 수 있습니다. 이 기능 만 추가하면됩니다 :

rdom () { local IFS=\> ; read -d \< E C ;}

이제 rdom을 읽기와 비슷하지만 HTML 문서에 사용할 수 있습니다. rdom을 호출하면 요소를 변수 E에, 내용을 var C에 할당합니다.

예를 들어 원하는 작업을 수행하려면

while rdom; do
    if [[ $E = title ]]; then
        echo $C
        exit
    fi
done < xhtmlfile.xhtml > titleOfXHTMLPage.txt

셸 스크립트에서 호출 할 수있는 명령 줄 도구는 다음과 같습니다.

  • 4xpath -Python의 4Suite 패키지를 둘러싼 명령 줄 래퍼
  • XMLStarlet
  • xpath-Perl의 XPath 라이브러리를 둘러싼 명령 줄 래퍼
  • Xidel- 파일 및 URL과 함께 작동합니다. JSON 과도 작동

또한 XSL 변환 스크립트가 거의없는 xmllint 및 xsltproc을 사용하여 명령 줄 또는 셸 스크립트에서 XML 처리를 수행합니다.


xpath 유틸리티를 사용할 수 있습니다. Perl XML-XPath 패키지와 함께 설치됩니다.

용법:

/usr/bin/xpath [filename] query

또는 XMLStarlet 입니다. opensuse에 설치하려면 다음을 사용하십시오.

sudo zypper install xmlstarlet

또는 cnf xml다른 플랫폼에서 시도하십시오 .


이것으로 충분합니다 ...

xpath xhtmlfile.xhtml '/html/head/title/text()' > titleOfXHTMLPage.txt

XML을 라인 지향 형식으로 변환하는 http://www.ofb.net/~egnor/xml2/ 에서 XML2확인하십시오 .


차드의 대답에서 시작하여, 여기에는 주석을 적절하게 처리하고 2 개의 작은 기능 (2 bu 이상을 모두 혼합 할 수 있음)으로 UML을 구문 분석하는 완벽한 작업 솔루션이 있습니다. 나는 chad의 것이 전혀 작동하지 않았다고 말하지는 않지만 형식이 잘못된 XML 파일과 관련하여 너무 많은 문제가있었습니다. 따라서 주석과 잘못 배치 된 공백 / CR / TAB 등을 처리하는 것이 조금 더 까다 롭습니다.

이 답변의 목적은 perl, python 또는 다른 것을 사용하는 복잡한 도구없이 UML을 구문 분석 해야하는 모든 사람에게 즉시 사용 가능한 즉시 bash 함수를 제공하는 것입니다. 나에 관해서는 cpan을 설치할 수 없으며 이전에 사용중인 이전 운영 체제 용 펄 모듈을 설치할 수 없으며 파이썬을 사용할 수 없습니다.

먼저,이 포스트에서 사용 된 UML 단어의 정의 :

<!-- comment... -->
<tag attribute="value">content...</tag>

편집 : 업데이트 된 기능, 처리 :

  • Websphere xml (xmi 및 xmlns 속성)
  • 256 색의 호환되는 터미널이 있어야합니다
  • 회색 음영 24 개
  • IBM AIX bash 3.2.16 (1)에 대한 호환성이 추가되었습니다.

함수는 먼저 xml_read에 의해 재귀 적으로 호출되는 xml_read_dom입니다.

xml_read_dom() {
# https://stackoverflow.com/questions/893585/how-to-parse-xml-in-bash
local ENTITY IFS=\>
if $ITSACOMMENT; then
  read -d \< COMMENTS
  COMMENTS="$(rtrim "${COMMENTS}")"
  return 0
else
  read -d \< ENTITY CONTENT
  CR=$?
  [ "x${ENTITY:0:1}x" == "x/x" ] && return 0
  TAG_NAME=${ENTITY%%[[:space:]]*}
  [ "x${TAG_NAME}x" == "x?xmlx" ] && TAG_NAME=xml
  TAG_NAME=${TAG_NAME%%:*}
  ATTRIBUTES=${ENTITY#*[[:space:]]}
  ATTRIBUTES="${ATTRIBUTES//xmi:/}"
  ATTRIBUTES="${ATTRIBUTES//xmlns:/}"
fi

# when comments sticks to !-- :
[ "x${TAG_NAME:0:3}x" == "x!--x" ] && COMMENTS="${TAG_NAME:3} ${ATTRIBUTES}" && ITSACOMMENT=true && return 0

# http://tldp.org/LDP/abs/html/string-manipulation.html
# INFO: oh wait it doesn't work on IBM AIX bash 3.2.16(1):
# [ "x${ATTRIBUTES:(-1):1}x" == "x/x" -o "x${ATTRIBUTES:(-1):1}x" == "x?x" ] && ATTRIBUTES="${ATTRIBUTES:0:(-1)}"
[ "x${ATTRIBUTES:${#ATTRIBUTES} -1:1}x" == "x/x" -o "x${ATTRIBUTES:${#ATTRIBUTES} -1:1}x" == "x?x" ] && ATTRIBUTES="${ATTRIBUTES:0:${#ATTRIBUTES} -1}"
return $CR
}

그리고 두 번째 것 :

xml_read() {
# https://stackoverflow.com/questions/893585/how-to-parse-xml-in-bash
ITSACOMMENT=false
local MULTIPLE_ATTR LIGHT FORCE_PRINT XAPPLY XCOMMAND XATTRIBUTE GETCONTENT fileXml tag attributes attribute tag2print TAGPRINTED attribute2print XAPPLIED_COLOR PROSTPROCESS USAGE
local TMP LOG LOGG
LIGHT=false
FORCE_PRINT=false
XAPPLY=false
MULTIPLE_ATTR=false
XAPPLIED_COLOR=g
TAGPRINTED=false
GETCONTENT=false
PROSTPROCESS=cat
Debug=${Debug:-false}
TMP=/tmp/xml_read.$RANDOM
USAGE="${C}${FUNCNAME}${c} [-cdlp] [-x command <-a attribute>] <file.xml> [tag | \"any\"] [attributes .. | \"content\"]
${nn[2]}  -c = NOCOLOR${END}
${nn[2]}  -d = Debug${END}
${nn[2]}  -l = LIGHT (no \"attribute=\" printed)${END}
${nn[2]}  -p = FORCE PRINT (when no attributes given)${END}
${nn[2]}  -x = apply a command on an attribute and print the result instead of the former value, in green color${END}
${nn[1]}  (no attribute given will load their values into your shell; use '-p' to print them as well)${END}"

! (($#)) && echo2 "$USAGE" && return 99
(( $# < 2 )) && ERROR nbaram 2 0 && return 99
# getopts:
while getopts :cdlpx:a: _OPT 2>/dev/null
do
{
  case ${_OPT} in
    c) PROSTPROCESS="${DECOLORIZE}" ;;
    d) local Debug=true ;;
    l) LIGHT=true; XAPPLIED_COLOR=END ;;
    p) FORCE_PRINT=true ;;
    x) XAPPLY=true; XCOMMAND="${OPTARG}" ;;
    a) XATTRIBUTE="${OPTARG}" ;;
    *) _NOARGS="${_NOARGS}${_NOARGS+, }-${OPTARG}" ;;
  esac
}
done
shift $((OPTIND - 1))
unset _OPT OPTARG OPTIND
[ "X${_NOARGS}" != "X" ] && ERROR param "${_NOARGS}" 0

fileXml=$1
tag=$2
(( $# > 2 )) && shift 2 && attributes=$*
(( $# > 1 )) && MULTIPLE_ATTR=true

[ -d "${fileXml}" -o ! -s "${fileXml}" ] && ERROR empty "${fileXml}" 0 && return 1
$XAPPLY && $MULTIPLE_ATTR && [ -z "${XATTRIBUTE}" ] && ERROR param "-x command " 0 && return 2
# nb attributes == 1 because $MULTIPLE_ATTR is false
[ "${attributes}" == "content" ] && GETCONTENT=true

while xml_read_dom; do
  # (( CR != 0 )) && break
  (( PIPESTATUS[1] != 0 )) && break

  if $ITSACOMMENT; then
    # oh wait it doesn't work on IBM AIX bash 3.2.16(1):
    # if [ "x${COMMENTS:(-2):2}x" == "x--x" ]; then COMMENTS="${COMMENTS:0:(-2)}" && ITSACOMMENT=false
    # elif [ "x${COMMENTS:(-3):3}x" == "x-->x" ]; then COMMENTS="${COMMENTS:0:(-3)}" && ITSACOMMENT=false
    if [ "x${COMMENTS:${#COMMENTS} - 2:2}x" == "x--x" ]; then COMMENTS="${COMMENTS:0:${#COMMENTS} - 2}" && ITSACOMMENT=false
    elif [ "x${COMMENTS:${#COMMENTS} - 3:3}x" == "x-->x" ]; then COMMENTS="${COMMENTS:0:${#COMMENTS} - 3}" && ITSACOMMENT=false
    fi
    $Debug && echo2 "${N}${COMMENTS}${END}"
  elif test "${TAG_NAME}"; then
    if [ "x${TAG_NAME}x" == "x${tag}x" -o "x${tag}x" == "xanyx" ]; then
      if $GETCONTENT; then
        CONTENT="$(trim "${CONTENT}")"
        test ${CONTENT} && echo "${CONTENT}"
      else
        # eval local $ATTRIBUTES => eval test "\"\$${attribute}\"" will be true for matching attributes
        eval local $ATTRIBUTES
        $Debug && (echo2 "${m}${TAG_NAME}: ${M}$ATTRIBUTES${END}"; test ${CONTENT} && echo2 "${m}CONTENT=${M}$CONTENT${END}")
        if test "${attributes}"; then
          if $MULTIPLE_ATTR; then
            # we don't print "tag: attr=x ..." for a tag passed as argument: it's usefull only for "any" tags so then we print the matching tags found
            ! $LIGHT && [ "x${tag}x" == "xanyx" ] && tag2print="${g6}${TAG_NAME}: "
            for attribute in ${attributes}; do
              ! $LIGHT && attribute2print="${g10}${attribute}${g6}=${g14}"
              if eval test "\"\$${attribute}\""; then
                test "${tag2print}" && ${print} "${tag2print}"
                TAGPRINTED=true; unset tag2print
                if [ "$XAPPLY" == "true" -a "${attribute}" == "${XATTRIBUTE}" ]; then
                  eval ${print} "%s%s\ " "\${attribute2print}" "\${${XAPPLIED_COLOR}}\"\$(\$XCOMMAND \$${attribute})\"\${END}" && eval unset ${attribute}
                else
                  eval ${print} "%s%s\ " "\${attribute2print}" "\"\$${attribute}\"" && eval unset ${attribute}
                fi
              fi
            done
            # this trick prints a CR only if attributes have been printed durint the loop:
            $TAGPRINTED && ${print} "\n" && TAGPRINTED=false
          else
            if eval test "\"\$${attributes}\""; then
              if $XAPPLY; then
                eval echo "\${g}\$(\$XCOMMAND \$${attributes})" && eval unset ${attributes}
              else
                eval echo "\$${attributes}" && eval unset ${attributes}
              fi
            fi
          fi
        else
          echo eval $ATTRIBUTES >>$TMP
        fi
      fi
    fi
  fi
  unset CR TAG_NAME ATTRIBUTES CONTENT COMMENTS
done < "${fileXml}" | ${PROSTPROCESS}
# http://mywiki.wooledge.org/BashFAQ/024
# INFO: I set variables in a "while loop" that's in a pipeline. Why do they disappear? workaround:
if [ -s "$TMP" ]; then
  $FORCE_PRINT && ! $LIGHT && cat $TMP
  # $FORCE_PRINT && $LIGHT && perl -pe 's/[[:space:]].*?=/ /g' $TMP
  $FORCE_PRINT && $LIGHT && sed -r 's/[^\"]*([\"][^\"]*[\"][,]?)[^\"]*/\1 /g' $TMP
  . $TMP
  rm -f $TMP
fi
unset ITSACOMMENT
}

마지막으로, rtrim, trim 및 echo2 (stderr로) 기능 :

rtrim() {
local var=$@
var="${var%"${var##*[![:space:]]}"}"   # remove trailing whitespace characters
echo -n "$var"
}
trim() {
local var=$@
var="${var#"${var%%[![:space:]]*}"}"   # remove leading whitespace characters
var="${var%"${var##*[![:space:]]}"}"   # remove trailing whitespace characters
echo -n "$var"
}
echo2() { echo -e "$@" 1>&2; }

채색 :

아 그리고 처음에는 깔끔한 채색 동적 변수를 정의하고 내 보내야합니다.

set -a
TERM=xterm-256color
case ${UNAME} in
AIX|SunOS)
  M=$(${print} '\033[1;35m')
  m=$(${print} '\033[0;35m')
  END=$(${print} '\033[0m')
;;
*)
  m=$(tput setaf 5)
  M=$(tput setaf 13)
  # END=$(tput sgr0)          # issue on Linux: it can produces ^[(B instead of ^[[0m, more likely when using screenrc
  END=$(${print} '\033[0m')
;;
esac
# 24 shades of grey:
for i in $(seq 0 23); do eval g$i="$(${print} \"\\033\[38\;5\;$((232 + i))m\")" ; done
# another way of having an array of 5 shades of grey:
declare -a colorNums=(238 240 243 248 254)
for num in 0 1 2 3 4; do nn[$num]=$(${print} "\033[38;5;${colorNums[$num]}m"); NN[$num]=$(${print} "\033[48;5;${colorNums[$num]}m"); done
# piped decolorization:
DECOLORIZE='eval sed "s,${END}\[[0-9;]*[m|K],,g"'

모든 것을로드하는 방법 :

FPATH (ksh) 또는 FPATH (bash) 에뮬레이션을 통해 함수를 작성하고로드하는 방법을 알고 있습니다.

그렇지 않은 경우 명령 행에서 모든 것을 복사 / 붙여 넣기 만하면됩니다.

작동 방식 :

xml_read [-cdlp] [-x command <-a attribute>] <file.xml> [tag | "any"] [attributes .. | "content"]
  -c = NOCOLOR
  -d = Debug
  -l = LIGHT (no \"attribute=\" printed)
  -p = FORCE PRINT (when no attributes given)
  -x = apply a command on an attribute and print the result instead of the former value, in green color
  (no attribute given will load their values into your shell as $ATTRIBUTE=value; use '-p' to print them as well)

xml_read server.xml title content     # print content between <title></title>
xml_read server.xml Connector port    # print all port values from Connector tags
xml_read server.xml any port          # print all port values from any tags

디버그 모드 (-d)를 사용하면 주석 및 구문 분석 된 속성이 stderr에 인쇄됩니다.


순수한 쉘 XML 파싱 도구를 모른다. 따라서 다른 언어로 작성된 도구가 필요할 것입니다.

내 XML :: Twig Perl 모듈에는 다음과 같은 도구가 포함되어 있습니다. xml_grep, 원하는 곳을 쓸 수 있습니다 xml_grep -t '/html/head/title' xhtmlfile.xhtml > titleOfXHTMLPage.txt( -t옵션은 결과를 XML 대신 텍스트로 제공합니다)


또 다른 명령 줄 도구는 새로운 Xidel 입니다. 또한 이미 언급 된 xpath / xmlstarlet과 달리 XPath 2 및 XQuery를 지원합니다.

제목은 다음과 같이 읽을 수 있습니다.

xidel xhtmlfile.xhtml -e /html/head/title > titleOfXHTMLPage.txt

또한 여러 변수를 bash로 내보내는 멋진 기능도 있습니다. 예를 들어

eval $(xidel xhtmlfile.xhtml -e 'title := //title, imgcount := count(//img)' --output-format bash )

파일 $title의 제목과 $imgcount이미지 수로 설정 합니다. 이는 파일을 bash에서 직접 파싱하는 것만 큼 유연해야합니다.


xpath 유틸리티를 사용할 수 있습니다. perl의 XML :: Xpath에 포함되어 있다고 생각합니다.


XML 파일에서 Linux와 Windows 형식의 파일 경로 변환에 대한 연구를 한 후 흥미로운 자습서와 솔루션을 찾았습니다.


원하는 기능을 수행 할 수있는 기성품 콘솔 유틸리티는 상당히 많지만, 쉽게 확장하고 적용 할 수있는 Python과 같은 범용 프로그래밍 언어로 몇 줄의 코드를 작성하는 데 시간이 덜 걸릴 것입니다 너의 요구.

다음은 lxml파싱에 사용하는 python 스크립트 입니다. 파일 또는 URL의 이름을 첫 번째 매개 변수로, XPath 표현식을 두 번째 매개 변수로 가져와 주어진 표현식과 일치하는 문자열 / 노드를 인쇄합니다.

실시 예 1

#!/usr/bin/env python
import sys
from lxml import etree

tree = etree.parse(sys.argv[1])
xpath_expression = sys.argv[2]

#  a hack allowing to access the
#  default namespace (if defined) via the 'p:' prefix    
#  E.g. given a default namespaces such as 'xmlns="http://maven.apache.org/POM/4.0.0"'
#  an XPath of '//p:module' will return all the 'module' nodes
ns = tree.getroot().nsmap
if ns.keys() and None in ns:
    ns['p'] = ns.pop(None)
#   end of hack    

for e in tree.xpath(xpath_expression, namespaces=ns):
    if isinstance(e, str):
        print(e)
    else:
        print(e.text and e.text.strip() or etree.tostring(e, pretty_print=True))

lxml와 함께 설치할 수 있습니다 pip install lxml. 우분투에서는을 사용할 수 있습니다 sudo apt install python-lxml.

용법

python xpath.py myfile.xml "//mynode"

lxml URL을 입력으로 허용합니다.

python xpath.py http://www.feedforall.com/sample.xml "//link"

참고 : XML에 접두사가없는 기본 네임 스페이스 (예 :)가 있으면 식에서 접두어 ( 'hack'으로 제공) xmlns=http://abc...를 사용해야합니다 p(예 : 파일 //p:module에서 모듈 가져 오기) pom.xml. 경우에 p접두사가 이미 XML에 매핑되는, 당신은 다른 접두사를 사용하는 스크립트를 수정해야합니다.


실시 예 2

아파치 메이븐 파일에서 모듈 이름을 추출하는 좁은 목적을 제공하는 일회용 스크립트. 노드 이름 ( module)에 기본 네임 스페이스가 접두어로 붙는 방법에 유의하십시오 {http://maven.apache.org/POM/4.0.0}.

pom.xml :

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modules>
        <module>cherries</module>
        <module>bananas</module>
        <module>pears</module>
    </modules>
</project>

module_extractor.py :

from lxml import etree
for _, e in etree.iterparse(open("pom.xml"), tag="{http://maven.apache.org/POM/4.0.0}module"):
    print(e.text)

Yuzem의 방법은 함수 및 변수 할당 에서 <>기호 의 순서를 반대로하여 개선 할 수 있습니다 rdom.

rdom () { local IFS=\> ; read -d \< E C ;}

된다 :

rdom () { local IFS=\< ; read -d \> C E ;}

이와 같이 구문 분석이 수행되지 않으면 XML 파일의 마지막 태그에 도달하지 않습니다. while루프 끝에서 다른 XML 파일을 출력하려는 ​​경우 문제가 될 수 있습니다 .


XML 속성을 원하는 경우 작동합니다.

$ cat alfa.xml
<video server="asdf.com" stream="H264_400.mp4" cdn="limelight"/>

$ sed 's.[^ ]*..;s./>..' alfa.xml > alfa.sh

$ . ./alfa.sh

$ echo "$stream"
H264_400.mp4

참고 URL : https://stackoverflow.com/questions/893585/how-to-parse-xml-in-bash

반응형