xml2 pode converter xml para / de formato orientado a linhas:
xml2 < pom.xml | grep /project/version= | sed 's/.*=//'
Eu quero ler um pom.xml ('Project Object Model' do Maven) e extrair as informações da versão. Aqui está um exemplo:
<?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>
Como posso extrair a versão '1.0.74-SNAPSHOT' de cima?
Adoraria poder fazer isso usando o simples script bash sed ou awk. Caso contrário, um simples python é o preferido.
EDITAR
Restrição
A caixa linux está em um ambiente corporativo, então eu só posso usar ferramentas que já estão instaladas (não que eu não possa solicitar utilitários como o xml2, mas eu tenho que passar por muita burocracia). Algumas das soluções são muito boas (aprenda alguns truques novos), mas elas podem não ser aplicáveis devido ao ambiente restrito
lista xml atualizada
Eu adicionei a tag de dependências à listagem original. Isso mostrará que alguma solução hacky pode não funcionar neste caso
Distro
A distro que estou usando é RHEL4
Usando 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
Usando 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
Usando 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
Outra maneira: xmlgrep e XPath:
xmlgrep --text_only '/project/version' pom.xml
Desvantagem: lenta
Caminho de Clojure. Requer apenas jvm com arquivo jar especial:
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))"
Caminho do Scala:
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 })'
Caminho Groovy:
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())'
Aqui está uma alternativa em Perl
$ perl -MXML::Simple -e'print XMLin("pom.xml")->{version}."\n"'
1.0.74-SNAPSHOT
Funciona com o exemplo revisado / estendido nas questões que têm vários elementos de "versão" em diferentes profundidades.
Hacky da maneira:
perl -e '$_ = join "", <>; m!<project[^>]*>.*\n(?: |\t)<version[^>]*>\s*([^<]+?)\s*</version>.*</project>!s and print "$1\n"' pom.xml
Baseia-se no recuo correto do <version>
necessário
Desenvolva uma solução muito desajeitada e de uma única linha
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/.*>\(.*\)<.*//g"
O sed no final é muito feio, mas eu não consegui imprimir o texto do nó com o mindom sozinho.
Atualizar de _Vi :
Versão Python menos hacky:
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()"
Atualização minha
Outra versão:
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']"
Caminho 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
se "Há muita tag de versão no xml", é melhor você esquecer de fazer isso com "simple tools" e regexps, isso não serve.
experimente este python (sem dependências):
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
Aqui está um one-liner usando sed:
sed '/<dependencies>/,/<\/dependencies>/d;/<version>/!d;s/ *<\/\?version> *//g' pom.xml
Return_text_val=$(xmllint --xpath "//*[local-name()='$TagElmnt']" $FILE )
Aqui, tente isto:
$TagElmnt - TagName
$FILE - xml file to parse
sed -n "/<name>project-parent/{n;s/.*>\(.*\)<.*//p;q}" pom.xml
A opção -n
evita imprimir linhas não correspondentes; a primeira correspondência ( /.../
) está na linha antes da que tem o texto desejado; o comando n
pula para a próxima linha, onde s
extrai informações relevantes através de um grupo de captura ( \(...\)
) e uma referência anterior ( ).
p
imprime, q
desiste.
Sei que sua pergunta diz Linux, mas se você precisa fazer isso no Windows sem a necessidade de ferramentas de terceiros para poder colocá-lo em um arquivo de lote, o Powershell pode extrair qualquer nó do seu pom.xml arquivo assim:
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