¿Cómo harían ustedes para agregar una línea a un montón de archivos XML después de ciertas etiquetas? La solución puede basarse en el uso de herramientas Unix o nombrar un editor de texto o utilidad que me permita hacer esto de forma rápida y sencilla. Tengo más de 60 archivos que necesito editar.
Por ejemplo tengo el siguiente XML:
<Node disablePersistence="true">
<Name>Mapper</Name>
<Action>
<Class-Name>com.test.component.Mapper</Class-Name>
<Param name="output_url" value="constant:file:///output.xml"/>
<Param name="xml_url" value="constant:file:///input.xml"/>
<Param name="xsl_url" value="constant:file:///template.xsl"/>
</Action>
<Next-Node>ComposeMessage</Next-Node>
</Node>
Primero necesitaría buscar la etiqueta Node. Entonces necesitaría buscar la etiqueta Nombre = Mapper. Luego busque la etiqueta Acción. Luego busque la etiqueta Param. Donde están todas las etiquetas para Param, debemos insertar la nueva línea:
<Param name="new_parameter" value="constant:true"/>
¿Es esto posible o es pedir demasiado y será más rápido editar manualmente todos los archivos?
Respuesta1
Aquí tienes, una solución que utiliza xmlstarlet
XPath. Extendí el XML para demostrar que podemos seleccionar nodos específicos:
Solución
xmlstarlet edit \
--subnode '//Node[Name/text()="Mapper"]/Action' --type elem --name 'Param' \
--var nap '$prev' \
--insert '$nap' --type attr --name 'name' --value 'new_parameter' \
--insert '$nap' --type attr --name 'constant:true'
Creamos un nuevo subnodo de Node/Action
donde también hay un elemento Name
que tiene el valor de texto Mapper
. Asignamos este nuevo nodo a la variable XPath nap
para que podamos hacer referencia a él fácilmente. Finalmente insertamos dos atributos en él.
XML de ejemplo
<root>
<Node disablePersistence="true">
<Name>Mapper</Name>
<Action>
<Class-Name>com.test.component.Mapper</Class-Name>
<Param name="output_url" value="constant:file:///output.xml"/>
<Param name="xml_url" value="constant:file:///input.xml"/>
<Param name="xsl_url" value="constant:file:///template.xsl"/>
</Action>
<Next-Node>ComposeMessage</Next-Node>
</Node>
<Node disablePersistence="true">
<Name>DoNotTouchMe</Name>
<Action>
<Class-Name>com.test.component.Mapper</Class-Name>
<Param name="output_url" value="constant:file:///output.xml"/>
<Param name="xml_url" value="constant:file:///input.xml"/>
<Param name="xsl_url" value="constant:file:///template.xsl"/>
</Action>
<Next-Node>ComposeMessage</Next-Node>
</Node>
</root>
Resultado
<root>
<Node disablePersistence="true">
<Name>Mapper</Name>
<Action>
<Class-Name>com.test.component.Mapper</Class-Name>
<Param name="output_url" value="constant:file:///output.xml"/>
<Param name="xml_url" value="constant:file:///input.xml"/>
<Param name="xsl_url" value="constant:file:///template.xsl"/>
<Param name="new_parameter" constant:true=""/>
</Action>
<Next-Node>ComposeMessage</Next-Node>
</Node>
<Node disablePersistence="true">
<Name>DoNotTouchMe</Name>
<Action>
<Class-Name>com.test.component.Mapper</Class-Name>
<Param name="output_url" value="constant:file:///output.xml"/>
<Param name="xml_url" value="constant:file:///input.xml"/>
<Param name="xsl_url" value="constant:file:///template.xsl"/>
</Action>
<Next-Node>ComposeMessage</Next-Node>
</Node>
</root>