Wie würdet ihr vorgehen, um einer Reihe von XML-Dateien nach bestimmten Tags eine Zeile hinzuzufügen? Die Lösung kann in der Verwendung von Unix-Tools bestehen oder darin, einen Texteditor oder ein Dienstprogramm zu nennen, mit dem ich dies schnell und einfach erledigen kann. Ich habe über 60 Dateien, die ich bearbeiten muss.
Ich habe beispielsweise das folgende 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>
Zuerst müsste ich nach dem Tag Node suchen. Dann müsste ich nach dem Tag Name = Mapper suchen. Dann nach dem Tag Action suchen. Dann nach dem Tag Param suchen. Wo alle Tags für Param sind, müssen wir dann die neue Zeile einfügen:
<Param name="new_parameter" value="constant:true"/>
Ist das möglich oder ist das zu viel verlangt und wäre es schneller, alle Dateien manuell zu bearbeiten?
Antwort1
Hier ist eine Lösung mit xmlstarlet
XPath. Ich habe das XML erweitert, um zu zeigen, dass wir bestimmte Knoten auswählen können:
Lösung
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'
Wir erstellen einen neuen Unterknoten von , Node/Action
in dem sich ebenfalls ein Element Name
mit dem Textwert befindet Mapper
. Diesem neuen Knoten weisen wir die XPath-Variable zu, nap
damit wir ihn einfach referenzieren können. Abschließend fügen wir ihm noch zwei Attribute hinzu.
Beispiel-XML
<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>
Ergebnis
<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>