2012-01-26 14 views
6

Ho un tipico pom.xml e voglio stampare groupId, artefatto ID e versione, separati da due punti. Penso che lo XMLStarlet sia lo strumento giusto per questo. Ho provato diversi modi, ma ottengo sempre una linea vuota.XMLStarlet non seleziona nulla

xml sel -t -m project -v groupId -o : -v artifactId -o : -v version pom.xml 

uscita prevista:

org.something.apps:app-acct:5.4 

uscita reale: riga vuota

Anche se provo a stampare solo il groupId non ottengo niente:

Sono sicuro che lo strumento vede gli elementi perché posso elencarli senza problemi:

xml el pom.xml 

stampa il seguente (correttamente):

project 
project/modelVersion 
project/parent 
project/parent/groupId 
project/parent/artifactId 
project/parent/version 
project/groupId 
project/artifactId 
project/version 
project/packaging 

Cosa c'è di sbagliato?

Qui è la versione ridotta di 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/maven-v4_0_0.xsd"> 

    <modelVersion>4.0.0</modelVersion> 

    <parent> 
     <groupId>org.something</groupId> 
     <artifactId>base</artifactId> 
     <version>1.16</version> 
    </parent> 

    <groupId>org.something.apps</groupId> 
    <artifactId>app-acct</artifactId> 
    <version>5.4</version> 
    <packaging>war</packaging> 

</project> 

risposta

28

Purtroppo, xmlstarlet è molto esigente circa il namespace di default. Se il documento ha dichiarato (xmlns=), si deve dichiarare per xmlstarlet troppo, e il prefisso gli elementi con il nome che avete scelto (vedi here):

xml sel -N mia = http://maven.apache.org/POM/4.0.0 -t - m il mio: progetto -v mia: groupId -o: -v mia: artifactId -o: -v mia: versione pom.xml

eseguire il comando sopra dà i risultati attesi:

org.something.apps:app-acct:5.4 

Tuttavia, se il documento NON ha il de fault namespace dichiarato (o lo spazio dei nomi ha un URL leggermente diverso), il comando sopra non funzionerà, che è un vero PITA. Una soluzione più universale è rimuovere la dichiarazione dello spazio dei nomi predefinita prima di selezionare gli elementi. A partire dal xmlstarlet 1.3.1, la conversione di XML in formato PYX e ritorno rimuove le dichiarazioni di namespace:

xml pisside pom.xml | xml p2x | xml sel -t -m progetto -v groupId -o: -v artifactId -o: -v versione 2> nul

UPDATE (2014/02/12): come del xmlstarlet 1.4.2 la pisside < -> La conversione XML è fissa (non rimuove le dichiarazioni dello spazio dei nomi), quindi il comando sopra non funzionerà (grazie per Peter Gluck per il suggerimento). Utilizzare invece il seguente comando:

xml pyx pom.xml | grep -v^A | xml p2x | xml sel -t -m progetto -v groupId -o: -v artifactId -o: versione -v

Nota: il grep sopra rimuove tutti gli attributi dal documento, non solo dichiarazioni di namespace. Per questo caso specifico (selezionando i valori degli elementi da pom.XML in cui non sono previsti elementi con namespace non predefinite) è ok, ma per un XML generale si eliminerebbe solo la dichiarazione dello spazio dei nomi di default (s) e nient'altro:

xml pisside pom.xml | grep -v "^ Axmlns" | xml p2x | xml sel -t progetto -m -v groupId -o: -v artifactId -o: versione -v


Nota (obsoleto): il reindirizzamento di errore (2>nul) è necessario nascondere la denuncia relativa al (oggi) sconosciute namespace XSI:

-: 1.28: namespace prefix xsi per schemaLocation il progetto non è definito

Un altro modo per sbarazzarsi di denuncia è di rimuovere la schemaLocation a tributo (in realtà, questo comando rimuove tutti gli attributi dal documento PYX, non solo xsi: schemaLocation):

xml pyx pom.xml | grep -v^A | xml p2x | xml sel -t progetto -m -v groupId -o: -v artifactId -o: versione -v

+0

Il tuo commento sugli elementi di prefisso con (alias per?) Lo spazio dei nomi dichiarato è la differenza cruciale per i documenti collegati. – chernevik

5

L'XML> PYX - trucco> XML non ha funzionato per me (utilizzando xmlstarlet versione 1.4.2) . Tuttavia, il XMLStarlet documentation contiene questo a portata di mano sed di comando che rimuove le dichiarazioni degli spazi dei nomi da un documento XML:

sed -e 's/ xmlns.*=".*"//g' 

che ha funzionato. Per la domanda originale, la sintassi sarebbe:

cat pom.xml | sed -e 's/ xmlns.*=".*"//g' | xml sel -t -m project -v groupId -o : -v artifactId -o : -v version 
+0

Grazie per l'aggiornamento sulla modifica di PYX -> conversione XML. Ciò significa che l'ultima riga di comando (con grep -v^A) è ora la preferita. Comunque, sed/grep/awk ecc. NON dovrebbe essere usato su XML generale: funziona per quel semplice esempio specifico nella documentazione (e anche per il mio esempio semplificato), ma potrebbe facilmente creare un documento XML non valido. Esempio: eseguendo il comando "handy" su questo: a = "X"; ritorno a; darà come risultato: uk4sx