Маніпулювання командним рядком XML (скриптом оболонки)


9

Як маніпулювати XML з командного рядка в скрипті оболонки?

Існує багато команд для маніпулювання табличними даними, заміни змінної середовища або заміни текстових фрагментів на регулярні вирази, але я не знайшов нічого для XML.

У моєму скрипті побудови потрібно вставити тег із вмістом у основний тег документа xml, і я вважаю за надмірне встановлення для цієї мети java, perl або python в ОС (мої сценарії виконуються в gitlab із зображеннями докера, так що моя робота з інструментами, доступними в Maven: зображення 3,5-jdk-8 було б мрією).

Я не хочу маніпулювати XML за допомогою sed, хоча в моєму сценарії побудови це спрацювало б, бо це зло .

Приклад: у мене є наступний xml:

<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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>  
  <!-- a lot of other tags-->
</project>  

І я хочу вставити наступний блок:

<distributionManagement>
    <repository>
        <id>private-releases</id>
        <url>https://my.private.server.com/nexus/repository/maven-releases/</url>
    </repository>
</distributionManagement>

всередині тегу проекту (і абсолютно не має значення, буде він на початку чи в кінці


опублікуйте свій вхід xml та очікуваний вихід
RomanPerekhrest

Отже, специфічні вимоги стосуються аналізатора XML, до якого можна викликати командний рядок, який не реалізований жодною з основних мов скриптів, але автономною утилітою C або C ++ (або іншою компільованою)?
Kusalananda

@Kusalanda Я вказав, що я запускаю науковці в докерних контейнерах, тому для мене найголовніше додати якомога менше зображення докерного зображення.
9ilsdx 9rvj 0lo

Якщо у вас є зображення з maven та jdk, то для мене Java здається найкращим варіантом .... чому ви вважаєте Java важкою вагою в цьому випадку?
Даніель Приден

Напевно, варто задати це питання щодо переповнення стека та позначення тегом maven- я підозрюю, що є кращий спосіб зробити те, що ви намагаєтеся зробити в самому Maven.
Даніель Приден

Відповіді:


10

XMLStarlet ( http://xmlstar.sourceforge.net/overview.php ) написаний на C та використовує libxml2та libxslt.

З огляду на документ XML

<?xml version="1.0"?>
<root>
  <tag>data</tag>
</root>

субнод, який rootможна вставити за допомогою

xml ed -s '/root' -t elem -n 'newtag' -v 'newdata' file.xml

який виробляє

<?xml version="1.0"?>
<root>
  <tag>data</tag>
  <newtag>newdata</newtag>
</root>

Вставте багато речей (тут використовуйте оригінал file.xmlвгорі):

xml ed -s '/root' -t elem -n 'newtag' \
       -s '/root/newtag' -t elem -n 'subtag' -v 'subdata' file.xml

Це виробляє

<?xml version="1.0"?>
<root>
  <tag>data</tag>
  <newtag>
    <subtag>subdata</subtag>
  </newtag>
</root>

Для прикладу в питанні:

xml ed -N x="http://maven.apache.org/POM/4.0.0" \
       -s '/x:project' -t elem -n 'distributionManagement' \
       -s '/x:project/distributionManagement' -t elem -n 'repository' \
       -s '/x:project/distributionManagement/repository' -t elem -n 'id' \
         -v 'private-releases' \
       -s '/x:project/distributionManagement/repository' -t elem -n 'url' \
         -v 'https://my.private.server.com/nexus/repository/maven-releases/' \
    file.xml

Результат:

<?xml version="1.0"?>
<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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  <!-- a lot of other tags-->
  <distributionManagement>
    <repository>
      <id>private-releases</id>
      <url>https://my.private.server.com/nexus/repository/maven-releases/</url>
    </repository>
  </distributionManagement>
</project>

Вставлення попередньо підготовленого XML-файлу в місці в XML:

Якщо припустити, що початковий XML з питання є в, file.xmlа додаткові біти, які повинні перейти в новий distributinManagementвузол, є new.xml(але не сам тег вузла), можна зробити наступне, щоб вставити new.xmlв кореневий вузол:

xml ed -N x="http://maven.apache.org/POM/4.0.0" \
       -s '/x:project' -t elem -n 'distributionManagement' \
       -v "$(<new.xml)" file.xml | xml unesc | xml fo

XMLStarlet автоматично уникнути даних , яка потребує в тікають, такі як <і >символи. xml unescБіт декодує введені дані (це фактично декодує весь документ, який може або не може бути проблемою) і xml foпереформатує отриманий XML - документ.

Результат -

<?xml version="1.0"?>
<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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  <!-- a lot of other tags-->
  <distributionManagement>
    <repository>
      <id>private-releases</id>
      <url>https://my.private.server.com/nexus/repository/maven-releases/</url>
    </repository>
  </distributionManagement>
</project>

Мені крихітно трохи неприємно робити це так, "але це працює".

Дивіться також це пов’язане питання на StackOverflow: /programming/29298507/xmlstarlet-xinclude-xslt


Це виглядає цікаво, хоча для вставки більше одного тегу синтаксис досить довгий. Тільки те, що в ubuntu воно називається "xmlstarlet". Чи можна вставити вміст іншого файлу як тег, якщо припустити, що вміст є дійсним xml?
9ilsdx 9rvj 0ло

@ 9ilsdx9rvj0lo Дивіться оновлену відповідь.
Кусалаланда

"він фактично не розглядає весь документ, який може бути, а може і не бути проблемою". Так, масовий випуск, усі існуючі та підсилювачі; були Unencoded викликаючи XML , щоб більше не дійсна :(
обікрасти

1

Мені здається зайвим встановити для цієї мети java, perl або python в ОС (мої сценарії виконуються в gitlab із зображеннями докера, тому виконувати свою роботу з інструментами, доступними в maven: 3.5-jdk-8 зображення було б мрією).

це, мабуть, все ще є надмірним, але якщо ви переймаєтесь лише розміром контейнера, ви можете використовувати дуже легку мову, наприклад, Lua або Guile.

з документів Lua:

Додавання Lua до програми не змушує її. Тарбол для Lua 5.3.4, який містить вихідний код та документацію, має стислий 297K та нестиснений 1,1M. Джерело містить близько 24000 рядків C. Під 64-розрядним Linux інтерпретатор Lua, побудований зі всіма стандартними бібліотеками Lua, займає 246K, а бібліотека Lua - 421K.


Варто подумати просто додати LUA до контейнера Maven, дякую за пораду.
9ilsdx 9rvj 0ло
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.