parts item empty attribute xml bash dynamic text replace

item - Reemplazar el contenido dinámico en el archivo XML



xml prolog (3)

Resumen rápido: Necesito crear una secuencia de comandos Bash para cambiar el texto dentro de un nodo automáticamente cada semana. El script coincidirá con el nodo y reemplazará el texto dentro de ellos (si es posible)? ¿Cómo haría esto?

Resumen largo: alojo un servidor de Minecraft que tiene tiendas, cada una de las cuales tiene su propio archivo .xml en el directorio / ShowcaseStandalone / ffs-storage /. Todos los domingos, mi servidor se reinicia y ejecuta varios comandos en el terminal para restablecer varias cosas. Una cosa que estoy tratando de hacer es cambiar una de las tiendas. Deseo cambiar el texto en el nodo <itemstack> y el texto en el nodo <price>. Simplemente quiero tomar texto de un archivo .txt en una carpeta diferente e insertarlo en ese nodo. El problema es que el texto en el nodo cambiará cada semana. ¿Hay alguna manera de reemplazar una línea o texto específico dentro de dos nodos usando bash?

Archivo 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>

Sistema operativo: Linux Ubuntu 12.04


La forma XML es genial, pero si necesita usar las herramientas normales de bash, puede modificar una línea usando sed. Por ejemplo:

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

Esto reemplazará el precio con 123.

Ese comando sed parece desalentador, así que déjame dividirlo:

/(<price.*>/)[^<>]*/(<//price.*/) es el patrón que debe coincidir. /( ... /) son paréntesis para agrupar. <price.*> coincide con la etiqueta de precio de apertura. [^<>]* coincide con cualquier cosa excepto los paréntesis angulares, y en este caso coincidirá con el contenido de la etiqueta de precio. <//price.* coincide con el final de la etiqueta de precio. La barra diagonal hacia delante es un delimitador en sed, por lo que me escapo con una barra diagonal inversa.

/1$PRICE/2 es el texto con el que se reemplaza el texto coincidente. /1 refiere al primer grupo de paréntesis coincidente, que es la etiqueta de precio de apertura. $PRICE es la variable con el precio deseado en ella. /2 refiere al segundo grupo de paréntesis, en este caso la etiqueta de cierre.


No tuve el lujo de tener xmlstarlet. Encontré una solución aunque simplemente haciendo un reemplazo en línea;

template-parameters.xml

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

Retazo

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

Resultado

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


Puede usar xmlstarlet para editar un archivo XML en un shell como este:

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

NOTA

  • "/scs-shop/price[@type=''double'']" es una expresión Xpath
  • ver xmlstarlet ed --help