Я пытаюсь автоматизировать добавление новых подузлов в nexus-core-feature-3.16.1-02.xml, потому что мы используем некоторые плагины для работы, которые не поставляются с «коробочным» решением. Суть в том, что при выпуске новой версии nexus-контейнера у меня есть bash-скрипт, который запускает новую версию тестового контейнера и копирует новый XML-файл по умолчанию в нужную папку. Следующим шагом будет редактирование этого файла и добавление некоторых новых функций, чтобы плагин работал. Когда это сделано, старый контейнер останавливается, новый xml-заменяет старый, и я запускаю док-контейнер с сопоставленными данными nexus и default-xml. Для корректной работы этого плагина мне нужно внести некоторые изменения в файл default-xml. И я хочу использовать для этого xmlstarlet. Добавьте это в раздел «nexus-core-feature»:
<feature version = "1.0.9" prerequisite = "false" dependency = "false">nexus-repository-apt</feature>
</feature>
И это до конца файла xml-файла
<feature name = "nexus-repository-apt" description = "net.staticsnow:nexus-repository-apt" version = "1.0.10">
<details>net.staticsnow:nexus-repository-apt</details>
<bundle>mvn:net.staticsnow/nexus-repository-apt/1.0.10</bundle>
<bundle>mvn:org.apache.commons/commons-compress/1.18</bundle>
<bundle>mvn:org.tukaani/xz/1.8</bundle>
</feature>
</features>
Итак, я какое-то время гуглил и ТАК, но я все еще застрял. Например, этот случай: Как вставить новый элемент под другой с помощью xmlstarlet?
Кажется довольно простым сделать что-то подобное, и я попробовал это:
xmlstarlet ed -s /features/feature/feature -t elem -n featureTMP -v "nexus-apt-repositroy" \
-i //featureTMP -t attr -n "version" -v "1.0.9" \
-i //featureTMP P -t attr -n "prerequisite" -v "false" \
-i //featureTMP -t attr -n "dependency" -v "false" \
-r //featureTMP -v feature nexus-core-feature-3.16.1-02-features.xml
Я подозреваю, что моя ошибка была (и есть) в пути к узлам.
Следующим шагом было изучение узлов
xmlstarlet sel -t -c "/" nexus-core-feature-3.16.1-02-features.xml
На выходе был весь xml-файл, и вроде все в порядке
<features xmlns = "http://karaf.apache.org/xmlns/features/v1.4.0" name = "nexus-core-feature">
<feature name = "nexus-core-feature" description = "org.sonatype.nexus.assemblies:nexus-core-feature" version = "3.16.1.02">
<details>org.sonatype.nexus.assemblies:nexus-core-feature</details>
<feature version = "3.16.1.02" prerequisite = "false" dependency = "false">nexus-audit-plugin</feature>
<feature version = "3.16.1.02" prerequisite = "false" dependency = "false">nexus-blobstore-tasks</feature>
<feature version = "3.16.1.02" prerequisite = "false" dependency = "false">nexus-ssl-plugin</feature>
<feature version = "3.16.1.02" prerequisite = "false" dependency = "false">nexus-coreui-plugin</feature>
<feature version = "3.16.1.02" prerequisite = "false" dependency = "false">nexus-repository-httpbridge</feature>
...
Но когда я пытаюсь попасть в узел, результат всегда пустой:
xmlstarlet sel -t -c "/features" nexus-core-feature-3.16.1-02-features.xml
С селектором атрибутов он по-прежнему пуст:
xmlstarlet sel -t -c "/features/feature[@name = "nexus-core-feature"]" nexus-core-feature-3.16.1-02-features.xml
Пробовал проверить это в тестере XPath-online, внутри тестера все в порядке.
Далее я использую более простой пример в этой статье: https://unix.stackexchange.com/questions/386965/insert-custom-xml-tag-into-a-xml-file-in-a-bash-script
и попытался просмотреть файл примера, который был в arctilce, и, похоже, все в порядке.
xmlstarlet sel -t -c "/server-groups" file.xml
выход:
<server-groups>
<server-group name = "main-server-group" profile = "full">
<jvm name = "default">
<heap size = "64m" max-size = "512m"/>
<jvm-options>
<option value = "somevalue"/>
</jvm-options>
</jvm>
<socket-binding-group ref = "full-sockets"/>
</server-group>
</server-groups>
Следующий шаг
xmlstarlet sel -t -c "/server-groups/server-group/jvm" file.xml
выход:
<jvm name = "default">
<heap size = "64m" max-size = "512m"/>
<jvm-options>
<option value = "somevalue"/>
</jvm-options>
</jvm>
И это меня очень смущает... Почему тот же подход не работает с файлом nexus-xml? Более сложная\странная структура? Буду рад любому совету





Why the same approach doesn't work with nexus-xml file?
Это потому, что ваш XML-файл Nexus находится в пространстве имен по умолчанию (http://karaf.apache.org/xmlns/features/v1.4.0).
Если вы используете xmlstarlet версии 1.0.5 или более поздней, вы можете использовать _: в своем XPath для соответствия любому пространству имен. В противном случае вам придется привязать пространство имен к префиксу с помощью -N. Посмотреть здесь для получения дополнительной информации.
Вот обновленный пример вашей первой попытки:
xmlstarlet ed -s /_:features/_:feature -t elem -n featureTMP -v "nexus-repository-apt" \
-i //featureTMP -t attr -n "version" -v "1.0.9" \
-i //featureTMP -t attr -n "prerequisite" -v "false" \
-i //featureTMP -t attr -n "dependency" -v "false" \
-r //featureTMP -v feature nexus-core-feature-3.16.1-02-features.xml
Вот альтернативный подход к использованию -N...
xmlstarlet ed -N f = "http://karaf.apache.org/xmlns/features/v1.4.0" -s /f:features/f:feature -t elem -n featureTMP -v "nexus-repository-apt" \
-i //featureTMP -t attr -n "version" -v "1.0.9" \
-i //featureTMP -t attr -n "prerequisite" -v "false" \
-i //featureTMP -t attr -n "dependency" -v "false" \
-r //featureTMP -v feature nexus-core-feature-3.16.1-02-features.xml
Оба они производят следующий вывод:
<features xmlns = "http://karaf.apache.org/xmlns/features/v1.4.0" name = "nexus-core-feature">
<feature name = "nexus-core-feature" description = "org.sonatype.nexus.assemblies:nexus-core-feature" version = "3.16.1.02">
<details>org.sonatype.nexus.assemblies:nexus-core-feature</details>
<feature version = "3.16.1.02" prerequisite = "false" dependency = "false">nexus-audit-plugin</feature>
<feature version = "3.16.1.02" prerequisite = "false" dependency = "false">nexus-blobstore-tasks</feature>
<feature version = "3.16.1.02" prerequisite = "false" dependency = "false">nexus-ssl-plugin</feature>
<feature version = "3.16.1.02" prerequisite = "false" dependency = "false">nexus-coreui-plugin</feature>
<feature version = "3.16.1.02" prerequisite = "false" dependency = "false">nexus-repository-httpbridge</feature>
<feature version = "1.0.9" prerequisite = "false" dependency = "false">nexus-repository-apt</feature>
</feature>
</features>
Добавить второй feature можно таким же образом, но вы также можете упростить все это, используя XSLT в xmlstarlet с tr команда. (В любом случае, на мой взгляд, это проще.)
XSLT (test.xsl)
<xsl:stylesheet version = "1.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
xmlns:f = "http://karaf.apache.org/xmlns/features/v1.4.0"
xmlns = "http://karaf.apache.org/xmlns/features/v1.4.0"
exclude-result-prefixes = "f">
<xsl:output indent = "yes"/>
<xsl:strip-space elements = "*"/>
<xsl:template match = "@*|node()">
<xsl:copy>
<xsl:apply-templates select = "@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match = "f:features">
<xsl:copy>
<xsl:apply-templates select = "@*|node()"/>
<feature name = "nexus-repository-apt" description = "net.staticsnow:nexus-repository-apt" version = "1.0.10">
<details>net.staticsnow:nexus-repository-apt</details>
<bundle>mvn:net.staticsnow/nexus-repository-apt/1.0.10</bundle>
<bundle>mvn:org.apache.commons/commons-compress/1.18</bundle>
<bundle>mvn:org.tukaani/xz/1.8</bundle>
</feature>
</xsl:copy>
</xsl:template>
<xsl:template match = "f:feature[@name='nexus-core-feature']">
<xsl:copy>
<xsl:apply-templates select = "@*|node()"/>
<feature version = "1.0.9" prerequisite = "false" dependency = "false">nexus-repository-apt</feature>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
команда xmlstarlet
xmlstarlet tr test.xsl nexus-core-feature-3.16.1-02-features.xml
Выход
<features xmlns = "http://karaf.apache.org/xmlns/features/v1.4.0" name = "nexus-core-feature">
<feature name = "nexus-core-feature" description = "org.sonatype.nexus.assemblies:nexus-core-feature" version = "3.16.1.02">
<details>org.sonatype.nexus.assemblies:nexus-core-feature</details>
<feature version = "3.16.1.02" prerequisite = "false" dependency = "false">nexus-audit-plugin</feature>
<feature version = "3.16.1.02" prerequisite = "false" dependency = "false">nexus-blobstore-tasks</feature>
<feature version = "3.16.1.02" prerequisite = "false" dependency = "false">nexus-ssl-plugin</feature>
<feature version = "3.16.1.02" prerequisite = "false" dependency = "false">nexus-coreui-plugin</feature>
<feature version = "3.16.1.02" prerequisite = "false" dependency = "false">nexus-repository-httpbridge</feature>
<feature version = "1.0.9" prerequisite = "false" dependency = "false">nexus-repository-apt</feature>
</feature>
<feature name = "nexus-repository-apt" description = "net.staticsnow:nexus-repository-apt" version = "1.0.10">
<details>net.staticsnow:nexus-repository-apt</details>
<bundle>mvn:net.staticsnow/nexus-repository-apt/1.0.10</bundle>
<bundle>mvn:org.apache.commons/commons-compress/1.18</bundle>
<bundle>mvn:org.tukaani/xz/1.8</bundle>
</feature>
</features>
@АфанасьевДмитрий - Рад, что смог помочь!
Спасибо за отличный ответ Даниил! Кажется, это рабочее решение для меня, но все же нужно немного отредактировать для моего случая :)