Заменить динамический контент в XML файле

Краткая сводка: Мне нужно создать Bash script, чтобы автоматически менять текст в node каждую неделю. script будет соответствовать node и заменить текст внутри них (если это возможно)? Как мне это сделать?

Длинное резюме: У меня есть сервер Minecraft, в котором есть магазины, каждый из которых имеет свой собственный .xml файл в каталоге /ShowcaseStandalone/ffs -storage/. Каждое воскресенье мой сервер перезапускает и выполняет несколько команд в терминале до reset несколько вещей. Одна вещь, которую я пытаюсь сделать, - это один из магазинов. Я хочу изменить текст в node <itemstack> и текст в node " цена > . Я просто хочу взять текст из .txt файла в другую папку и вставить его в node. Проблема в том, что текст в node будет меняться каждую неделю. Есть ли способ заменить определенную строку или текст в двух узлах с помощью bash?

XML файл:

<?xml version="1.0" encoding="UTF-8"?>
<scs-shop usid="cac8480951254352116d5255e795006252d404d9" version="2" type="storage">
    <enchantments type="string"/>
    <owner type="string">Chadward27</owner>
    <world type="string">Frisnuk</world>
    <itemStack type="string">329:0</itemStack>
    <activity type="string">BUY</activity>
    <price type="double">55.0</price>
    <locX type="double">487.5</locX>
    <locY type="double">179.0</locY>
    <locZ type="double">-1084.5</locZ>
    <amount type="integer">0</amount>
    <maxAmount type="integer">0</maxAmount>
    <isUnlimited type="boolean">true</isUnlimited>
    <nbt-storage usid="23dffac5fb2ea7cfdcf0740159e881026fde4fa4" version="2" type="storage"/>
</scs-shop>

Операционная система: Linux Ubuntu 12.04

Ответы

Ответ 1

Вы можете использовать xmlstarlet для редактирования файла XML в shell следующим образом:

xmlstarlet edit -L -u "/scs-shop/price[@type='double']" -v '99.66' file.xml

Примечание

  • "/scs-shop/price[@type='double']" - выражение Xpath
  • см. xmlstarlet ed --help

Ответ 2

XML-способ классный, но если вам нужно использовать обычные инструменты bash, вы можете изменить строку с помощью sed. Например:

PRICE=123
sed -i "s/\(<price.*>\)[^<>]*\(<\/price.*\)/\1$PRICE\2/" $XML_FILE_TO_MODIFY

Это заменит цену на 123.

Эта команда sed кажется сложной, поэтому позвольте мне сломать ее:

\(<price.*>\)[^<>]*\(<\/price.*\) соответствует шаблону. \(... \) являются скобками для группировки. <price.*> соответствует начальному ценнику. [^<>]* соответствует чему угодно, кроме угловых скобок, и в этом случае будет соответствовать содержимому ценника. <\/price.* соответствует концу ценника. Прямая косая черта - это разделитель в sed, поэтому я избегаю ее с обратной косой чертой.

\1$PRICE\2 - это текст для замены согласованного текста. \1 относится к первой сопоставленной группе скобок, которая является начальным ценовым тегом. $PRICE - это переменная с желаемой ценой. \2 относится ко второй группе скобок, в этом случае закрывающий тег.

Ответ 3

У меня не было роскоши иметь xmlstarlet. Я нашел решение, просто сделав встроенную замену;

шаблон-parameter.xml

<ns:Parameter>
    <ns:Name required="true">##-ParamName-##</ns:Name>
    <ns:Value>
        <ns:Text>##-ParamValue-##</ns:Text>
    </ns:Value>
</ns:Parameter>

Отрывок

tokenName="foo"
tokenValue="bar"    

#Replace placeholders in parameter template element
myParamElement=$(cat template-parameter.xml)
myParamElement=${myParamElement//##-ParamName-##/$tokenName}
myParamElement=${myParamElement//##-ParamValue-##/$tokenValue}  

Результат

<ns:Parameter>
    <ns:Name required="true">foo</ns:Name>
    <ns:Value>
        <ns:Text>bar</ns:Text>
    </ns:Value>
</ns:Parameter>