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