2017-02-01 4 views
0

Ich habe Text, der über ihm mehrere XML-Blöcke mit Metadaten enthält, wie folgt aus:python regex: match Wörter in einem mehrzeiligen Muster

Block 1 
2017-02-01 12:00 
<?xml version="1.0" encoding="UTF-8"?> 
<block> 
<elt>text</elt> 
<elt>more text</elt> 
<block> 
    <elt>words</elt> 
</block> 
</block> 

Block 2 
2017-02-01 12:15 
<?xml version="1.0" encoding="UTF-8"?> 
<block> 
<block> 
    <elt>text</elt> 
    <block> 
    <elt>words</elt> 
    </block> 
    <elt>more text</elt> 
</block> 
<elt>word</elt> 
</block> 

Ich brauche den XML-Text zu ziehen und die Metadaten überspringen. Ich kann es wie folgt iterativ tun:

messages = [] 
while True: 
start = xml.find('<?xml') 
if start == -1: 
    break 
xml = xml[start:] 
end = xml.find('\n\n') 
if end == -1: 
    messages.append(xml) 
    break 
else: 
    messages.append(xml[:end]) 
    xml = xml[end:] 

Aber ich möchte stattdessen einen regulären Ausdruck verwenden. Das Problem, das ich habe, ist, dass ich entweder 2 aufeinanderfolgende Zeilenumbrüche (\n\n) oder das Ende der Zeichenfolge (\Z) übereinstimmen muss. Ich habe Probleme dort. Ich habe es versucht:

re.findall('<\?xml.*?[\n\n|\Z]', xml, re.DOTALL) 

aber ich bekomme nur ['<?xml version="1.0" encoding="UTF-8"?>\n', '<?xml version="1.0" encoding="UTF-8"?>\n'].

Ich habe \b in der Vergangenheit verwendete Worte übereinstimmen, aber das gibt keine Änderung:

>>> re.findall('<\?xml.*?[(\b\n\n\b)|\Z]', xml, re.DOTALL) 
['<?xml version="1.0" encoding="UTF-8"?>\n', '<?xml version="1.0" encoding="UTF-8"?>\n'] 

Ich kann nicht herausfinden, wie es funktioniert.

Antwort

1

Sie versuchen, Ende der Zeichenfolge oder 2 Zeilenumbrüche in einer Zeichenklasse []. Das funktioniert nicht.

ich sie in einem Forward-Lookup entsprechen würde (nicht verbrauchen oder Gruppen im Gegensatz zu Standard-Gruppierung Klammern erstellen, so kehrt findall die gesamte Zeichenkette)

re.findall('<\?xml.*?(?=\n\n|\Z)', xml, re.DOTALL) 

Eine weitere gute Abhilfe für dieses wäre die passen letzte </block>, auf einer neuen Zeile beginnen:

re.findall('<\?xml.*?\n</block>', xml, re.DOTALL) 
+0

Matching auf '' ist unsicher, da, wenn die Top-Level-Tag-Änderungen, die das Muster bricht. das '(? =' ist was ich gesucht habe. Danke. – ewok