PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Regex, um in Notepad++ Daten aus XML zu extrahieren


Mr. Lolman
2021-09-23, 16:29:06
<xmlheader>
<header1>
<ds id=1234567><a>bla<a><info><f>128</f><g>bla</g></info><f>129</f><g>bla</g></info></ds>
<dsfooter><dsfooter>
<ds id=1234568><a>bla<a><info><f>130</f><g>bla</g></info><f>131</f><g>bla</g></info></ds>
<dsfooter><dsfooter>
</header1>


Habt ihr eine Idee, wie ich mir die Werte für id und f mittels Notepad extrahieren kann? Ich scheitere trotz längerem probieren (bin kein Regex checker) daran, 128 und 129 in einer Zeile zu bekommen.

Mein Ansatz war alle Inhalte außer f (und nachher noch id) zu eliminieren:

Suche nach .+<f>(.+)</f>.+
Ersetzen durch \1

mit Option [x] . findet \n und \r

Damit bleibt mit dann genau 131 über. Das Endergebnis sollte aber wie folgt aussehen:

1234567;128;129
1234568;130;131

Geht das überhaupt mit Notepad++?

Monger
2021-09-23, 16:34:44
Greedy Operatoren sind immer für Überraschungen gut. Besser man vermeidet die.

<f>([^<]+)</f>

Sofern Notepad++ alle Treffer nimmt, sollte das gehen.

RattuS
2021-09-25, 01:07:57
Wenn du nur ein RegEx-Replace im Editor hast, geht eigentlich nur ein Lookahead und der bringt dir trotzdem nicht genau den Output, den du erwartest. Einfachste Lösung: JavaScript.

Pack das in eine lokale .html Datei, setz dein (kaputtes?) XML ein und kopier dir die Ausgabe der Konsole in deine CSV oder wo auch immer du damit hinwillst:

<script>

const xml = `
<xmlheader>
<header1>
<ds id=1234567><a>bla<a><info><f>128</f><g>bla</g></info><f>129</f><g>bla</g></info></ds>
<dsfooter><dsfooter>
<ds id=1234568><a>bla<a><info><f>130</f><g>bla</g></info><f>131</f><g>bla</g></info></ds>
<dsfooter><dsfooter>
</header1>
`;

function extractStuff(input) {

const re = new RegExp('id=["\']?([0-9]+)["\']?|<f[^>]*>([0-9]+)</f>', 'g');

let result = [];

const parts = input.split('</ds>');
parts.forEach(part => {

const matches = [ ...part.matchAll(re) ];
if (!matches) { return; }

let row = matches.map(entry => {

return ( entry[1] ? entry[1] : entry[2] );
});
if (!row.length) { return; }

result.push( row.join(';') );
});

return result;
};

console.log(
extractStuff(xml).join('\n')
);

</script>

https://i.imgur.com/pfX0Bxq.png

Falls dein XML, anders als im Beispiel, well-formed vorliegt, solltest du sowas wie:


const doc = new DOMParser().parseFromString(xml, 'application/xml');
const nodes = doc.querySelectorAll('ds[id], f');


bevorzugen, denn damit kannst du sauber über alles Nodes laufen.

lumines
2021-09-25, 13:30:23
Geht das überhaupt mit Notepad++?

Generell ist XML keine reguläre Sprache, daher kann man es auch nicht mit regulären Ausdrücken beschreiben. Wenn man nur ein Subset von XML parsen will, das sich mit regulären Ausdrücken beschreiben lässt (je nach dem kann das ja vielleicht der Fall sein), dann kann es unter Umständen funktionieren, aber im allgemeinen Fall wird es nicht funktionieren.

Ich würde auch einfach das XML durch einen Parser jagen und dann die entsprechenden Werte extrahieren. Wenn es nicht wohlgeformt oder kaputt ist, dann wird dir nichts anderes übrig bleiben als es manuell irgendwie zu extrahieren.

Als "Dirty Hack" kann aber auch so etwas in z.B. AWK funktionieren, wenn du WSL installiert hast:

$ awk 'BEGIN { FS=">"; OFS=";" } /^<ds id=/ { split($1, a, "="); split($6, b, "<"); split($11, c, "<"); print a[2], b[1], c[1] }' mytestfile.xml
1234567;128;129
1234568;130;131

Wohlgemerkt habe ich hier bis auf das "/^<ds id=/", um die relevanten Zeilen zu extrahieren, keine regulären Ausdrücke benutzt. Ich verlasse mich hier nur darauf, dass die Tags an bestimmten Stellen auftauchen und splitte dort an den relevanten Stellen, speichere alles in Arrays und hole mir dann die relevanten Werte aus den Arrays. Von daher funktioniert das natürlich nur, wenn deine Datei exakt diese Form hat.

littlejam
2021-09-25, 16:59:35
Die Zeilen, die du suchst kannst du hiermit in das Format überführen...
Suchen:
.*?id=(\d+).*?<f>(\d+)</f>.*?<f>(\d+)</f><g>bla</g></info></ds>.*?
Ersetzen:
\1;\2;\3\n
Haken bei Regex und "findet \r und \n"

Damit bleibt nur noch die letzten 2 Zeilen als Überschuss übrig.

Grüße

Mr. Lolman
2021-10-07, 21:18:49
Vielen Dank für die Tipps. :up: