Подтвердить что ты не робот

Собственная команда оболочки для извлечения значения 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 за вашу помощь.

4b9b3361

Ответ 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