스크립팅 : XML 파일의 태그에서 값을 추출하는 가장 쉬운 방법은 무엇입니까?


14

pom.xml (Maven의 'Project Object Model')을 읽고 버전 정보를 추출하고 싶습니다. 예를 들면 다음과 같습니다.

<?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/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>
    <groupId>com.mycompany</groupId>
    <artifactId>project-parent</artifactId>
    <name>project-parent</name>
    <version>1.0.74-SNAPSHOT</version>
    <dependencies>
        <dependency>
        <groupId>com.sybase.jconnect</groupId>
        <artifactId>jconnect</artifactId>
        <version>6.05-26023</version>
    </dependency>
    <dependency>
        <groupId>joda-time</groupId>
        <artifactId>joda-time</artifactId>
        <version>1.5.2</version>
    </dependency>
    <dependency>
        <groupId>com.sun.jdmk</groupId>
        <artifactId>jmxtools</artifactId>
        <version>1.2.1</version>
    </dependency>
    <dependency>
        <groupId>org.easymock</groupId>
        <artifactId>easymock</artifactId>
        <version>2.4</version>
    </dependency>       
</dependencies>
</project>

위에서 '1.0.74-SNAPSHOT'버전을 어떻게 추출 할 수 있습니까?

간단한 bash 스크립팅 sed 또는 awk를 사용하여 그렇게 할 수 있기를 바랍니다. 그렇지 않으면 간단한 파이썬이 선호됩니다.

편집하다

  1. 강제

    리눅스 상자는 회사 환경에 있으므로 이미 설치된 도구 만 사용할 수 있습니다 (xml2와 같은 유틸리티를 요청할 수는 없지만 많은 빨간 테이프를 거쳐야합니다). 일부 솔루션은 매우 우수하지만 (몇 가지 새로운 트릭을 이미 배우십시오) 제한된 환경으로 인해 적용되지 않을 수 있습니다

  2. 업데이트 된 XML 목록

    원본 태그에 dependencies 태그를 추가했습니다. 이 경우 해키 솔루션이 작동하지 않을 수 있습니다.

  3. 배포

    내가 사용하는 배포판은 RHEL4입니다.



실제로는 아닙니다. xml에는 많은 버전 태그가 있습니다 (예 : dependencies 태그 아래). '/ project / version'만 원합니다
Anthony Kong

어떤 XML 관련 도구 및 라이브러리를 사용할 수 있습니까? jvm 기반 솔루션이 정상입니까?
Vi.

지금까지 xml2, xmlgrep 및 perl XML 모듈이 없다고 말할 수 있습니다. 대부분의 유닉스 명령 줄 유틸리티가 있습니다. 배포판은 Redhat EL 4입니다.
Anthony Kong

(댓글을 추가 할 수 없어 답글로 답장을
보내야

답변:


17

xml2는 xml을 라인 지향 형식으로 변환 할 수 있습니다.

xml2 < pom.xml  | grep /project/version= | sed 's/.*=//'

6

다른 방법 : xmlgrep 및 XPath :

xmlgrep --text_only '/project/version' pom.xml

단점 : 느리게


업데이트] 명령xml_grep
GAD3R

6

사용 python

$ python -c 'from xml.etree.ElementTree import ElementTree; print ElementTree(file="pom.xml").findtext("{http://maven.apache.org/POM/4.0.0}version")'
1.0.74-SNAPSHOT

사용 xmlstarlet

$ xml sel -N x="http://maven.apache.org/POM/4.0.0" -t -m 'x:project/x:version' -v . pom.xml
1.0.74-SNAPSHOT

사용 xmllint

$ echo -e 'setns x=http://maven.apache.org/POM/4.0.0\ncat /x:project/x:version/text()' | xmllint --shell pom.xml | grep -v /
1.0.74-SNAPSHOT

cat (//x:version)[1]/text()사용할 xmllint때도 작동합니다!
kev

5

클로저 방식. 특수 jar 파일이있는 jvm 만 필요합니다.

java -cp clojure.jar clojure.main -e "(use 'clojure.xml) (->> (java.io.File. \"pom.xml\") (clojure.xml/parse) (:content) (filter #(= (:tag %) :version)) (first) (:content) (first) (println))"

스칼라 방법 :

java -Xbootclasspath/a:scala-library.jar -cp scala-compiler.jar scala.tools.nsc.MainGenericRunner -e 'import scala.xml._; println((XML.load(new java.io.FileInputStream("pom.xml")) match { case <project>{children @ _*}</project> => for (i <- children if (i  match { case <version>{children @ _*}</version> => true; case _ => false;  }))  yield i })(0) match { case <version>{Text(x)}</version> => x })'

그루비 방식 :

java -classpath groovy-all.jar groovy.ui.GroovyMain -e 'println (new XmlParser().parse(new File("pom.xml")).value().findAll({ it.name().getLocalPart()=="version" }).first().value().first())'

대단해! 좋은 생각이야!
Anthony Kong

4

Perl의 대안은 다음과 같습니다.

$ perl -MXML::Simple -e'print XMLin("pom.xml")->{version}."\n"'
1.0.74-SNAPSHOT

깊이가 다른 여러 "버전"요소가있는 질문에서 수정 / 확장 된 예제와 함께 작동합니다.


느리다 (xmlgrep보다 빠르지 만)
Vi.

3

해키 웨이 :

perl -e '$_ = join "", <>; m!<project[^>]*>.*\n(?:    |\t)<version[^>]*>\s*([^<]+?)\s*</version>.*</project>!s and print "$1\n"' pom.xml

필요한 정확한 들여 쓰기에 의존 <version>


제안에 감사하지만 불행히도 내가 원하는 것을 반환하지는 않습니다. 업데이트 된 pom 모델을 참조하십시오.
Anthony Kong

"1.0.74-SNAPSHOT"를 반환합니다. 여러 <version>가지 에 대해 읽은 후 스크립트를 변경했습니다 .
Vi.

참고 :이 솔루션은 "재미있게"제공되며 실제 제품에는 사용되지 않습니다. xml2 / xmlgrep / XML :: Simple 솔루션을 더 잘 사용하십시오.
Vi.

감사! 심지어 '그냥 재미'이지만 아마 그 종속성의 최소 수를 가지고 멀리 있기 때문에 의해 '가장 적합한'솔루션입니다 비록 : 그것은 단지 필요 펄 ;-)
안토니 홍콩

Java에서 수행하는 것은 어떻습니까? pom 파일을 사용한다는 것은 JVM이 설치되었음을 의미합니다.
Vi.

3

매우 서투른 단일 라이너 솔루션을 개발하십시오.

python -c "from xml.dom.minidom import parse;dom = parse('pom.xml');print [n for n in dom.getElementsByTagName('version') if n.parentNode == dom.childNodes[0]][0].toxml()" | sed -e "s/.*>\(.*\)<.*/\1/g"

끝에있는 sed는 매우 못 생겼지 만 mindom만으로 노드의 텍스트를 인쇄 할 수 없었습니다.

_Vi에서 업데이트 :

덜 해킹 된 파이썬 버전 :

python -c "from xml.dom.minidom import parse;dom = parse('pom.xml');print [i.childNodes.item(0).nodeValue for i in dom.firstChild.childNodes if i.nodeName == 'version'].pop()"

나에게서 업데이트

다른 버전 :

    python -c "from  xml.dom.minidom import parse;dom = parse('pom.xml');print [n.firstChild.data for n in dom.childNodes[0].childNodes if n.firstChild and n.tagName == 'version']"

2

XSLT 방식 :

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="text"/>

        <xsl:template match="/">
                <xsl:for-each select="*[local-name()='project']">
                    <xsl:for-each select="*[local-name()='version']">
                        <xsl:value-of select="text()"/>
                    </xsl:for-each>
                </xsl:for-each>
        </xsl:template>
</xsl:stylesheet>
xalan -xsl x.xsl -in pom.xml

xsltproc이 시스템에 있고 libxslt가 RHEL4에있는 것 같으면 위의 스타일 시트를 사용하여 태그를 출력 할 수 있습니다 (예 : xsltproc x.xsl prom.xsl).
fpmurphy

2

"xml에 많은 버전 태그가있는 경우" "간단한 도구"및 정규식으로 수행하는 것을 잊어 버리는 것이 좋습니다.

이 파이썬을 사용해보십시오 (종속성이 없음).

from xml.dom.minidom import parse

dom = parse('pom.xml')
project = dom.getElementsByTagName('project')[0]
for node in project.childNodes:
    if node.nodeType == node.ELEMENT_NODE and node.tagName == 'version':
        print node.firstChild.nodeValue

이 스크립트는 정확히 무엇을합니까?
Simon Sheehan

: 그것은 파이썬의 minidom 구현을 사용하여 DOM 구조로 XML로드 docs.python.org/library/xml.dom.minidom.html (직접 자식 노드를 통해 다음으로 반복 아이디어가 <프로젝트>를 잡아 것입니다 고유 태그를 childs 만 해당) Google에서 찾고있는 <version> 태그를 찾고 다른 위치에서 동일한 이름을 가진 다른 태그는 찾지 않습니다.
Samus_

1

다음은 sed를 사용하는 하나의 라이너입니다.

sed '/<dependencies>/,/<\/dependencies>/d;/<version>/!d;s/ *<\/\?version> *//g' pom.xml

1
요소에 매개 변수 <version>가 없으며 추가 요소 는 내부 종속성에만있을 수 있습니다.
Vi.

1

추가 도구를 사용하지 않고 awk가 제대로 작동합니다.
cat pod.xml

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.networks.app</groupId>
  <artifactId>operation-platform</artifactId>
  <version>1.0.0</version>
  <packaging>tar.xz</packaging>
  <description>POM was created by Sonatype Nexus</description>
</project>

<packaging>태그 의 가치를 얻는 간단하고 읽기 쉬운 방법 :

cat pod.xml | awk -F'[<>]' '/packaging/{print $3}'

1
이것은 작동하는 것처럼 보이지만주의하십시오. FS (field separator)는 문자 세트 <및>로 설정됩니다. 그런 다음 "packaging"이라는 단어가 포함 된 모든 줄을 찾아 세 번째 필드를 제공합니다.
SMerrill8

0
Return_text_val=$(xmllint --xpath "//*[local-name()='$TagElmnt']" $FILE )

여기, 이것을보십시오 :

$TagElmnt - TagName
$FILE - xml file to parse

0

귀하의 질문에 Linux가 있다고 알고 있지만 배치 파일에 넣을 수있는 타사 도구없이 Windows 에서이 작업을 수행 해야하는 경우 Powershell은 pom.xml 파일에서 노드를 추출 할 수 있습니다 :

powershell -Command "& {select-xml //pom:project/pom:properties/pom:mypluginversion -path pom.xml -Namespace  @{pom='http://maven.apache.org/POM/4.0.0'} | foreach {$_.Node.Innerxml}}" > myPluginVersion.txt

Powershell은 이제 오픈 소스이며 Linux 및 기타 플랫폼에서 실행됩니다. 우리는 bash, cygwin 및 ming64보다 우선적으로 빌드하는 데 사용합니다.
Charlweed

0
sed -n "/<name>project-parent/{n;s/.*>\(.*\)<.*/\1/p;q}" pom.xml

-n옵션은 일치하지 않는 줄을 인쇄하지 않도록합니다. 첫 번째 일치 ( /.../)는 원하는 텍스트가있는 행보다 앞에 있습니다. 이 n명령은 다음 행으로 건너 뜁니다. 여기서 s캡처 그룹 ( \(...\)) 및 역 참조 ( \1)를 통해 관련 정보를 추출 합니다. p인쇄하고 q종료합니다.


2
이것을 설명하기 위해 답을 넓힐 수 있습니까? 감사.
fixer1234
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.