Agregar una línea a un archivo XML después de etiquetas específicas

Agregar una línea a un archivo XML después de etiquetas específicas

¿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 xmlstarletXPath. 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/Actiondonde también hay un elemento Nameque tiene el valor de texto Mapper. Asignamos este nuevo nodo a la variable XPath nappara 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>

información relacionada