XMLStarlet ничего не выбирает - PullRequest
16 голосов
/ 27 января 2012

У меня типичный файл pom.xml, и я хочу напечатать идентификатор группы, идентификатор артефакта и версию, разделенные двоеточием. Я думаю, что XMLStarlet - правильный инструмент для этого. Я пробовал несколько способов, но всегда получаю пустую строку.

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

Ожидаемый результат:

org.something.apps:app-acct:5.4

Реальный вывод: пустая строка

Даже если я попытаюсь распечатать только группу, я ничего не получу:

xml sel -t -v project/groupId pom.xml

Я уверен, что инструмент видит элементы, потому что я могу перечислить их без проблем:

xml el pom.xml

печатает следующее (правильно):

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

Что не так?

Вот урезанная версия 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>

Ответы [ 2 ]

38 голосов
/ 27 января 2012

К сожалению, XMLStarlet очень требователен к пространству имен по умолчанию.Если в документе объявлено (xmlns=), вы должны объявить его и для XMLStarlet и добавить к элементам имя, которое вы выбрали (см. здесь ):

xml sel -N my = http://maven.apache.org/POM/4.0.0 -t -m my: проект -v my: groupId -o: -v my: artifactId -o: -v my: версия pom.xml

Выполнение вышеуказанной команды дает ожидаемый результат:

org.something.apps:app-acct:5.4

Однако, если документ НЕ имеет объявленного пространства имен по умолчанию (или пространство имен имеет немного другой URL), вышеуказанная команда НЕ будет работать, которая является настоящей PITA.Более универсальным решением является удаление объявления пространства имен по умолчанию перед выбором элементов.Начиная с XMLStarlet 1.3.1, преобразование XML в формат PYX и обратно удаляет объявления пространства имен:

xml pyx pom.xml |xml p2x |xml sel -t -m project -v groupId -o: -v artifactId -o: -v версия 2> nul

ОБНОВЛЕНИЕ (2014-02-12): asXMLStarlet 1.4.2 XML-преобразование PYX <-> исправлено (не удаляет объявления пространства имен), поэтому приведенная выше команда НЕ будет работать (спасибо за подсказку Питеру Глуку).Вместо этого используйте следующую команду:

xml pyx pom.xml |grep -v ^ A |xml p2x |xml sel -t -m project -v groupId -o: -v artifactId -o: -v версия

Примечание. Приведенный выше grep удаляет ВСЕ атрибуты из документа, а не только объявления пространства имен.Для этого конкретного случая (выбор значений элементов из pom.xml, где элементы с пространствами имен не по умолчанию не ожидаются) это нормально, но для общего XML вы удалили бы только объявление (я) пространства имен по умолчанию и ничего больше:

xml pyx pom.xml |grep -v "^ Axmlns" |xml p2x |xml sel -t -m project -v groupId -o: -v artifactId -o: -v версия


Примечание (устарело): перенаправление ошибок (2>nul) необходимо дляскрыть жалобу на (теперь) неизвестное пространство имен xsi:

-: 1.28: Префикс пространства имен xsi для schemaLocation в проекте не определен

Другой способ избавиться отжалоба состоит в том, чтобы удалить атрибут schemaLocation (фактически эта команда удаляет все атрибуты из документа PYX, а не только xsi: schemaLocation):

xml pyx pom.xml |grep -v ^ A |xml p2x |xml sel -t -m project -v groupId -o: -v artifactId -o: -v версия

8 голосов
/ 22 мая 2013

Уловка XML-> PYX-> XML у меня не сработала (с использованием XMLStarlet версии 1.4.2).Однако документация XMLStarlet содержит эту удобную команду sed, которая удаляет объявления пространства имен из документа XML:

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

Это сработало.Для исходного вопроса синтаксис будет:

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