
Ich habe ein kniffliges Problem. Ich muss eine kleine Änderung an einer großen Anzahl von XML-Dateien (500+) vornehmen. Die Änderung beinhaltet das Ändern eines Wertes von „false“ in „true“. Die Zeile, die geändert werden muss, sieht folgendermaßen aus:
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
Und es muss werden:
<SizeIsMeasuredLineLine>true</SizeIsMeasuredLineLine>
Leider gibt es in jeder Datei zahlreiche Instanzen dieses Tag-Satzes, sodass wir nicht einfach suchen und ersetzen können. Das Besondere an diesem Tag-Satz ist, dass er einige Zeilen nach Folgendem kommt:
<CID>ITEMNAME.BUS.ITEMNAME.DKV</CID>
Da jedoch jede Datei einen anderen Elementnamen hat, habe ich Platzhalter verwendet, um sie herauszufiltern.
<CID>.*BUS..*.DKV</CID>
Das Problem ist, dass die Anzahl der Zeilen zwischen dem CID-Teil und der Zeile, die geändert werden muss, von Datei zu Datei nicht konsistent ist. Ich muss einen Weg finden, die Zeilen dazwischen durch Platzhalter zu ersetzen und die Größenzeile zu ersetzen.
Irgendwelche Ideen? Ich habe bereits versucht:
<CID>.*BUS..*.DKV</CID>.*?<SizeIsMeasuredLineLine>true</SizeIsMeasuredLineLine>
Aber aus irgendeinem Grund hat das nicht funktioniert. Vielen Dank im Voraus!
Als Antwort auf den Kommentar bearbeiten:
Im Wesentlichen möchte ich sagen, dass der Code folgendermaßen aussieht:
<CID>ITEMNAME.BUS.ITEMNAME.DKV</CID>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
Und andere Abschnitte im Code sehen so aus:
<CID>ITEMNAME.COLR.ITEMNAME.FCLR</CID>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
an anderen Stellen im Code. Ich verwende also die Zeile CID .BUS .DKV als Ausgangspunkt. Im Grunde muss ich das erste Vorkommen der Zeile SizeisMeasured ändern, das direkt NACH der Zeile CID .BUS .DKV kommt. Aber dazwischen gibt es viele andere Zeilen (von denen keine von Datei zu Datei konsistent ist), die mich nicht interessieren und meine Suche durcheinander bringen.
Antwort1
Sie können einen negativen Vorausblick wie folgt verwenden. Suche
(?!<CID>.*BUS..*.DKV</CID>(.*?))<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
und ersetzen durch
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
Regulärer Ausdruck, passend zu . newline
Negative Lookahead (?!a)
und Negative Lookbehind (?<!a)
werden auch als Lookaround bezeichnet. Lookaround gleicht Zeichen ab, gibt die Übereinstimmung dann aber auf und gibt nur das Ergebnis zurück: Übereinstimmung oder keine Übereinstimmung.
Mehr finden Sie hier Lookahead- und Lookbehind-Assertionen mit Nulllänge
Antwort2
Das Parsen von XML unter Berücksichtigung der Hierarchie mit regulären Ausdrücken ist unnötig schwierig. Ich würde ein völlig anderes Tool verwenden, das explizit für das entwickelt wurde, was Sie zu tun versuchen, nämlich XML zu transformieren. Ich spreche von XSLT. Hier ist also meine Lösung für Ihr Problem mit XSLT. Es gibt eine Reihe von Websites, auf denen Sie Ihr XML mit XSLT konvertieren können, oder Sie können XSLT lokal ausführen.
Das Problem wäre einfacher, wenn jede Ihrer Gruppen (CID gefolgt von SizeIsMeasuredLineLine) innerhalb eines einzigen übergeordneten Elements wäre, aber der folgende Code untersucht das erste vorangehende CID-Geschwisterelement, um zu sehen, welchen Wert es hat. Wenn es einen Wert hat, der dem regulären Ausdruck (ITEMNAME.[^.]+.ITEMNAME..+) entspricht, ändert er „false“ in „true“. Alle anderen Elemente werden einfach in die Ausgabe kopiert.
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="SizeIsMeasuredLineLine[matches(preceding-sibling::CID[1], 'ITEMNAME\.[^.]+\.ITEMNAME\..+')]">
<xsl:copy>TRUE</xsl:copy>
</xsl:template>
Hier ist das XML-Beispiel, das ich zum Testen des oben genannten erstellt habe:
<?xml version="1.0" encoding="UTF-8"?>
<parent>
<CID>ITEMNAME.BUS.ITEMNAME.DKV</CID>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
<CID>ITEMNAME.COLR.ITEMNAME.FCLR</CID>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
<CID>ITEMNAME.BUS.122.DKV</CID>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
<CID>ITEMNAME.COLR.ITEMNAME.FCLR</CID>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
<CID>ITEMNAME.BUS.44.DKV</CID>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
<CID>ITEMNAME.COLR.ITEMNAME.FCLR</CID>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
<CID>ITEMNAME.BUS.33.DKV</CID>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
<CID>ITEMNAME.COLR.ITEMNAME.FCLR</CID>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
</parent>