2013-06-06 22 views
23

Próbuję wyodrębnić wartość węzła z pom.xml:Native polecenie powłoki ustawić, aby wyodrębnić wartości węzła z XML

<?xml version="1.0" encoding="UTF-8"?> 
<project> 
    <parent> 
     <groupId>org.me.labs</groupId> 
     <artifactId>my-random-project</artifactId> 
     <version>1.5.0</version> 
    </parent> 
    ... 
</project> 

muszę wyodrębnić artifactId oraz wersję z użyciem XML polecenie powłoki. Mam następujące wymagania/obserwacje:

  1. Skrypt powłoki zostanie wykonany w pliku zespołu kompilacji, którego używamy w pracy, więc im mniejszy skrypt, tym lepiej.
  2. Ponieważ będzie używany na wielu systemach (zazwyczaj RHEL5), szukam czegoś, co może działać natywnie na domyślnych obrazach.
  3. Tagi takie jak mogą wystąpić w innym miejscu w pom, więc nie mogę po prostu awk dla tych tagów.

Próbowałem następujące:

  1. xpath działa na moim Mac, ale nie jest domyślnie dostępne na maszynach RHEL. Podobnie jak w przypadku xmllint --xpath, które, jak sądzę, są dostępne tylko w późniejszych wersjach xmllint, których nie mam i których nie mogę wymusić.
  2. xmllint --pattern wydawało się obiecujące, ale nie mogę uzyskać wyjścia z xmllint --pattern '//project/parent/version' pom.xml (wypisuje cały plik XML) lub xmllint --stream --pattern '//project/parent/version' pom.xml (brak danych wyjściowych).

Zdaję sobie sprawę, że jest to powszechne pytanie na SO, ale powyższe punkty są powodem, dla którego nie mogę wykorzystać tych odpowiedzi. TIA za twoją pomoc.

Odpowiedz

14

udało mi się go rozwiązać na razie z tym raczej unwiedly skrypt używając xmllint --shell.

echo "cat //project/parent/version" | xmllint --shell pom.xml | sed '/^\/ >/d' | sed 's/<[^>]*.//g' 

Jeśli węzły XML mają nazw atrybutów jak moja pom.xml miał, robi się cięższy, w zasadzie ekstrakcji węzeł według nazwy:

echo "cat //*[local-name()='project']/*[local-name()='parent']/*[local-name()='version']" | xmllint --shell pom.xml | sed '/^\/ >/d' | sed 's/<[^>]*.//g' 

Nadzieję, że to pomaga. Jeśli ktokolwiek może po prostu wypowiadać te wyrażenia, byłbym wdzięczny.

+2

Alternatywnie można użyć następującego: 'echo" cat // * [local-name() = 'project']/* [local-name() = 'parent']/* [local-name() = 'wersja "]/text()" | xmllint --shell pom.xml | sed '/^\ />/d'', więc musisz tylko" sed "-usunąć powłokę xmllint stuff –

+0

Jeśli masz wystarczająco dużo' xmllint', to nie potrzebujesz rzeczy '--shell' : 'xmllint --xpath/* [nazwa lokalna() ==" projekt "]/... 'pom.xml'. Część 'local-name()' była tym, czego mi brakowało w moim skrypcie. – Guss

13

--format służy tylko do formatowania (wcięcia itp.) Dokumentu. Można to zrobić za pomocą --xpath (testowane w Ubuntu, libxml v20900):

$ xmllint --xpath "//project/parent/version/text()" pom.xml 
1.5.0 
+0

Jak mówiłem, moja wersja 'xmllint' nie wydają się potwierdzać' opcję --xpath'. I nie chcę przypadkiem, że będzie on dostępny w moich systemach kompilacji. –

+0

O, przykro mi, nie zauważyłem. python/libxml2 jest opcją? – Salem

+1

Również: 'xpath -q -e" // projekt/rodzic/wersja/tekst() "pom.xml' – Salem

3

Korzystanie z funkcji text() XPath daje wartość elementu, zamiast usunąć tagi XML:

echo "cat //project/parent/version/text()" | xmllint --shell pom.xml 
+0

Niestety tekst() nie działa ani nie ma wartości '/ value/text()' Z jakiej wersji biblioteki libxml2 korzystasz? Mam 2.7.6 – Dejan

5

Przyjechałem tu szuka miły sposób zeskrobać wartość ze strony internetowej. Poniższy przykład może być przydatny dla tych (w przeciwieństwie do plakatu), którzy mają wersję xmllint, która obsługuje - xpath.

Potrzebowałem pobrać najnowszą stabilną wersję pliku elasticsearch .deb i zainstalować ją. Opiekunowie pomocni umieścili numer wersji w rozpiętości z klasą "wersja".

version=`curl -s http://www.elasticsearch.org/download/ |\ 
xmllint --html --xpath '//span[@class="version"]/text()'\ 
2>/dev/null - `; 

Co dalej:

Używamy (cichy) opcję curl -s.

curl -s http://www.elasticsearch.org/download/ 

Używamy przełączników xmllint --html i --xpath. Argumenty XPath (w apostrofach)

'//span[@class="version"]/text()' 

... wygląda na < przęsła > węzła z atrybutem klasy (@class) "Wersja" i wydobywa wartość tekstową (/ text()).

Ponieważ xmllint jest (niespodzianka!) Linerem, będzie skandować o nieuniknionych śmieciach w strumieniu html. Kierujemy się stderr do/dev/null w zwykły sposób:

2>/dev/null 

Wreszcie należy zwrócić uwagę na „-” na końcu polecenia xmllint, który opowiada xmllint strumień pochodzi z stdin.

+2

Karthik. V, to nie jest dobra odpowiedź dla ciebie, ale twoje pytanie jest dobrze nazwane, więc jest dość wysoko w wyszukiwarce Google. Pomyślałem, że dodam to dla ludzi takich jak ja, którzy szukają szybkiej odpowiedzi i mają różne narzędzia. – lysdexia

-1

Można spróbować

xmllint --xpath "/*[name()='project']/*[name()='groupId']/text()" pom.xml

Powiązane problemy