Собственная команда оболочки для извлечения значения node из XML
Я пытаюсь извлечь значение node из pom.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>
Мне нужно извлечь artifactId и версию из XML с помощью команды оболочки. У меня есть следующие требования/наблюдения:
- Оболочка script будет выполнена в файле сборки, который мы используем на работе, поэтому чем меньше script, тем лучше.
- Так как он будет использоваться на нескольких системах (обычно RHEL5), я ищу что-то, что может запускаться изначально по умолчанию.
- Теги, подобные возможно, встречаются в другом месте в pom, поэтому я не могу просто awk для этих тегов.
Я пробовал следующее:
-
xpath
работает на моем Mac, но по умолчанию не работает на машинах RHEL. Аналогично для xmllint --xpath
, который, как я полагаю, доступен только в более поздних версиях xmllint
, которого у меня нет и не могу обеспечить.
-
xmllint --pattern
кажется многообещающим, но я не могу получить выход из xmllint --pattern '//project/parent/version' pom.xml
(печатает весь XML) или xmllint --stream --pattern '//project/parent/version' pom.xml
(без вывода).
Я понимаю, что это общий вопрос здесь о SO, но вышеприведенные пункты - вот почему я не могу использовать эти ответы. TIA за вашу помощь.
Ответы
Ответ 1
Мне удалось решить эту проблему с этим довольно неудобно script с помощью xmllint --shell
.
echo "cat //project/parent/version" | xmllint --shell pom.xml | sed '/^\/ >/d' | sed 's/<[^>]*.//g'
Если узлы XML имеют атрибуты пространства имен, подобные моему pom.xml, все становится тяжелее, в основном извлекая node по имени:
echo "cat //*[local-name()='project']/*[local-name()='parent']/*[local-name()='version']" | xmllint --shell pom.xml | sed '/^\/ >/d' | sed 's/<[^>]*.//g'
Надеюсь, это поможет. Если кто-то может просто эти выражения, я был бы благодарен.
Ответ 2
--format
используется только для форматирования (отступ и т.д.) документа. Вы можете сделать это с помощью --xpath
(проверено в Ubuntu, libxml v20900):
$ xmllint --xpath "//project/parent/version/text()" pom.xml
1.5.0
Ответ 3
Я пришел сюда, чтобы найти хороший способ скрестить ценность с веб-сайта. Следующий пример может быть полезен для тех (в отличие от плаката), у которых есть версия xmllint, которая поддерживает -xpath.
Мне нужно было вытащить самую последнюю стабильную версию elasticearch.debfile и установить ее. Сопровождающие успешно помещают номер версии в пролет с классом "версия".
version=`curl -s http://www.elasticsearch.org/download/ |\
xmllint --html --xpath '//span[@class="version"]/text()'\
2>/dev/null - `;
Что происходит:
Мы используем параметр curl -s (silent).
curl -s http://www.elasticsearch.org/download/
Мы используем переключатели xmllint --html и --xpath. Аргументы xpath (в одинарных кавычках)
'//span[@class="version"]/text()'
... ищет <span> node с атрибутом class (@class) "version" и извлекает текстовое значение (/text()).
Так как xmllint (сюрприз!) linter, он будет кричать о неизбежном мусоре в вашем потоке html. Мы направляем stderr на /dev/null обычным способом:
2>/dev/null
Наконец, обратите внимание на "-" в конце команды xmllint, которая сообщает xmllint, что поток поступает из stdin.
Ответ 4
Использование функции text()
XPath дает вам значение элемента, вместо того, чтобы удалять теги XML:
echo "cat //project/parent/version/text()" | xmllint --shell pom.xml
Ответ 5
Вы можете попробовать
xmllint --xpath "/*[name()='project']/*[name()='groupId']/text()" pom.xml