Komut dosyası oluşturma: XML dosyasının etiketindeki bir değeri ayıklamanın en kolay yolu nedir?


14

Bir pom.xml (Maven'in 'Proje Nesne Modeli') okumak ve sürüm bilgilerini çıkarmak istiyorum. İşte bir örnek:

<?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' sürümünü yukarıdan nasıl çıkarabilirim?

Basit bash komut dosyası sed veya awk kullanarak bunu yapabilmek isterdim. Aksi takdirde basit bir python tercih edilir.

DÜZENLE

  1. Kısıtlama

    Linux kutusu kurumsal bir ortamda, bu yüzden sadece zaten yüklü olan araçları kullanabilirim (xml2 gibi bir yardımcı program talep edemem, ancak bir sürü bürokrasiden geçmek zorunda değilim). Bazı çözümler çok iyi (zaten birkaç yeni püf noktası öğrenin), ancak kısıtlı ortam nedeniyle uygulanamayabilir

  2. güncellenmiş xml listesi

    Bağımlılıklar etiketini orijinal listeye ekledim. Bu, bazı hacky çözümlerinin bu durumda çalışmayabileceğini gösterecektir

  3. Distro

    Kullandığım dağıtım RHEL4



Pek sayılmaz. Xml'de çok fazla sürüm etiketi var (örn. Bağımlılıklar etiketi altında). Sadece '/ project / version' istiyorum
Anthony Kong

Hangi xml ile ilgili araçlar ve kütüphaneler mevcuttur? Jvm tabanlı çözümler iyi mi?
Vi.

Şimdiye kadar xml2, xmlgrep ve perl XML modülünün mevcut olmadığını söyleyebilirim. Çoğu unix komut satırı yardımcı programı vardır. Dağıtım Redhat EL 4'tür.
Anthony Kong

(Ben bir cevap ekleyemedim, bu yüzden bir cevap olarak cevap vermek zorundayım) Bazı büyük cevaplar burada bulunabilir ..... stackoverflow.com/questions/2735548/…
JStrahl

Yanıtlar:


17

xml2 xml'yi satır yönelimli biçime / biçime dönüştürebilir:

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

6

Diğer yol: xmlgrep ve XPath:

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

Dezavantaj: yavaş


komut güncellendixml_grep
GAD3R

6

kullanma 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

kullanma 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

kullanma 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()kullanırken xmllintde çalışır!
kev

5

Clojure yolu. Sadece özel jar dosyası ile jvm gerektirir:

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))"

Scala yolu:

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 })'

Harika yol:

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())'

Bu harika! İyi fikir!
Anthony Kong

4

İşte Perl'de bir alternatif

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

Farklı derinliklerde birden fazla "versiyon" elemanı olan sorularda gözden geçirilmiş / genişletilmiş örnekle çalışır.


Yavaş, (xmlgrep'den daha hızlı olmasına rağmen)
Vi.

3

Hacky yolu:

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

Gerekli doğru girintiye dayanır <version>


Öneri için teşekkürler, ama ne yazık ki ne istediğimi döndürmez. Lütfen güncellenmiş pom modeline bakın.
Anthony Kong

"1.0.74-SNAPSHOT" değerini döndürür. Birden çok <version>şeyi okuduktan sonra komut dosyasını değiştirdiğimi unutmayın .
Vi.

Not: Bu çözüm "sadece eğlence için" sağlanmıştır ve gerçek üründe kullanılması amaçlanmamıştır. Daha iyi kullanmak xml2 / xmlgrep / XML :: Basit çözüm.
Vi.

Teşekkürler! 'eğlence için' olsa da, muhtemelen en az bağımlılığa sahip olduğu için muhtemelen 'en uygun' çözümdür: Sadece perl ;-) gerektirir
Anthony Kong

Java'dan yapmaya ne dersiniz? Pom dosyalarının kullanılması JVM'nin kurulu olduğu anlamına gelir.
Vi.

3

Çok beceriksiz, tek katmanlı bir çözüm bulun

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"

Sonunda sed çok çirkin ama sadece mindom ile düğüm metnini yazdıramadı.

_Vi'den güncelleme :

Daha az hacky Python sürümü:

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()"

Benden güncelle

Başka bir sürüm:

    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 yolu:

<?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 sisteminizde varsa ve muhtemelen libxslt RHEL4'te olduğu gibi ise, etiketi ve yukarıdaki stil sayfasını kullanarak çıktı alabilirsiniz, yani xsltproc x.xsl prom.xsl.
fpmurphy

2

"xml'de çok sayıda sürüm etiketi var" ise, bunu "basit araçlar" ve normal ifadeler ile yapmayı unutursanız iyi olmaz.

bu python'u deneyin (bağımlılık yok):

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

Bu senaryo tam olarak ne yapıyor?
Simon Sheehan

XML'i Python'un minidom uygulamasını kullanarak bir DOM yapısı olarak yükler: docs.python.org/library/xml.dom.minidom.html buradaki fikir, benzersiz <project> etiketini almak ve daha sonra alt düğümleri üzerinde tekrarlamaktır (doğrudan yalnızca çocuklarda), başka yerlerde aynı ada sahip diğer etiketleri değil, aradığımız <sürüm> etiketini bulmak için.
Samus_

1

İşte sed kullanarak bir astar:

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

1
Elementlerde parametrelerin bulunmamasına ve ekstraların <version>sadece bağımlılıkların içinde olabileceğine güvenir .
Vi.

1

awk herhangi bir ekstra araç kullanmadan iyi çalışır.
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>etiketinin değerini almanın basit ve okunaklı yolu :

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

1
Bu işe yarıyor gibi görünüyor, ancak dikkat: Yaptığı şey alan ayırıcısını (FS) <ve> karakter kümesine ayarlamaktır; daha sonra "ambalaj" kelimesini içeren tüm satırları bulur ve size üçüncü alanı verir.
SMerrill8

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

İşte şunu deneyin:

$TagElmnt - TagName
$FILE - xml file to parse

0

Sorunuzun Linux dediğini biliyorum, ancak bunu bir toplu iş dosyasına koyabileceğiniz herhangi bir üçüncü taraf aracına ihtiyaç duymadan Windows'ta yapmanız gerekiyorsa, Powershell pom.xml dosyanızdaki herhangi bir düğümü çıkarabilir. :

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 artık açık kaynak kodlu ve Linux ve diğer platformlarda çalışıyor. Bunu bash, cygwin ve ming64 yerine inşa etmek için kullanıyoruz.
Charlweed

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

Bu -nseçenek, eşleşmeyen satırların yazdırılmasını önler; ilk eşleme ( /.../) istenen metne sahip olandan önceki satırda; nKomut sonraki satıra, atlar nerede sekstreler ilgili bir yakalama grubu aracılığıyla bilgi ( \(...\)) ve bir geribaşvuru ( \1). pyazdırır, qçıkar.


2
Bunu açıklamak için cevabınızı genişletebilir misiniz? Teşekkürler.
fixer1234
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.