2012-01-26 2 views
6

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

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

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

org.something.apps:app-acct:5.4 

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

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

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

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> 

ответ

28

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

XML Сель -N мой = http://maven.apache.org/POM/4.0.0 -t - м мой: проект -v мои: идентификатор_группы -о: -v мой: артефакт -o: -v моя: версия pom.xml

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

org.something.apps:app-acct:5.4 

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

xml pyx pom.xml | xml p2x | XML Сель -t -m проект -v идентификатор_группы -o: -o -v артефакта: -v версия 2> NUL

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

xml pyx pom.xml | grep -v^A | xml p2x | XML Сель -t -m проекта -v идентификатор_группы -o: -o -v артефакта: -v версия

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

XML Pyx pom.xml | grep -v "^ Axmlns" | xml p2x | XML Sel -t -m проект -v идентификатор_группа -o: -o -v артефакт: -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 проект -v идентификатор_группа -o: -o -v артефакт: -v версия

+0

Ваш комментарий о префиксах элементов с (псевдоним для?) Объявленного пространства имен является решающим отличием от связанных документов. – chernevik

5

XML-> PYX -> XML трюк не работает для меня (с использованием XMLStarlet версии 1.4.2) , Однако XMLStarlet documentation содержит эту удобный 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 
+0

Спасибо за обновление об изменении в PYX -> преобразование XML. Это означает, что последняя командная строка (с grep -v^A) теперь является предпочтительной. Однако sed/grep/awk и т. Д. НЕ должны использоваться в общем XML: он работает для этого конкретного простого примера в документации (и для моего упрощенного примера тоже), но он может легко создать недопустимый XML-документ. Пример: запуск этого «удобного» sed на этом: a = "X"; return a; приведет к следующему: uk4sx

Смежные вопросы