2017-04-12 4 views
0

Ich habe zu große XML zu analysieren. Wenn ein Knoten ausfällt, möchte ich weiterlaufen und mit den verbleibenden Knoten arbeiten.Parsing XML mit ungültigen Knoten

Version 1

for event, element in etree.iterparse(file): 
    if element.tag == "tag1": 
     # Doing some stuff 

mit der ersten Version erhalte ich eine Ausnahme:

ParseError: not well-formed (invalid token): line 319851 

So um die bleiben Knoten I eine zweite Version geschrieben haben zu verarbeiten:

Version 2

xml_parser = etree.iterparse(file) 

while True: 
    try: 
     event, element = next(xml_parser) 

     if element.tag == "tag1": 
      # Doing some stuff 
     # If there is no more elements to iterate, breaks the loop 
     except StopIteration: 
      break 

     # While another exception, keep looping 
     except Exception as e: 
      pass 

In diesem Fall das Skript in eine Endlosschleife eingeben.

So versuchte ich, als Textdatei auf die spezifische Linie Öffnung gehen:

with open(file) as fp: 
    for i, line in enumerate(fp): 
     if i == 319850: 
      print(319850, line) 
     if i == 319851: 
      print(319851, line) 
     if i == 319852: 
      print(319852, line) 
     if i == 319853: 
      print(319853, line) 

      break 

ich:

319850 <tag1> <tag11><![CDATA[ foo bar 

319851 ]]></tag11></tag1> 

319852 <tag1> <tag11><![CDATA[ foo bar]]></tag11></tag1> 

319853 <tag1> <tag11><![CDATA[ foo bar]]></tag11></tag1> 

scheint so, dass Linie zu sein, wird durch "\ n" zerschnitt. Das ist ein XML-Fehler, aber warum funktioniert meine zweite Version nicht? In meiner zweiten Version sind die Zeilen 319850 und 319851 nicht als XML gültig, daher sollten die nächsten Knoten/Zeilen übergeben werden.

Was mache ich hier falsch? Wenn Sie einen besten Ansatz haben, lassen Sie es mich wissen.

UPDATE

XML-Datei hat ein ungültiges Zeichen '\ X0B'. So sieht so aus:

<tag1> <tag11><![CDATA[ foo bar '\x0b']]></tag11></tag1> 
<tag1> <tag11><![CDATA[ foo bar]]></tag11></tag1> 
<tag1> <tag11><![CDATA[ foo bar]]></tag11></tag1> 
+0

Ein Zeilenumbruch in einem CDATA-Abschnitt ist kein XML-Fehler. Wie können wir das reproduzieren? – mzjn

+0

@mzjn bitte, siehe mein Update –

+0

Siehe http://stackoverflow.com/questions/20078816/replace-non-ascii-characters-with-a-single-space zum Beispiel. –

Antwort

0

ich diese Linien haben, die Probleme zu sein scheinen zu verursachen und stopfte sie in eine etwas größere XML-Datei für Testzwecke. Das ist es.

<whole> 
<tag1> 
<tag11>one</tag11> 
<tag11><![CDATA[ foo bar 
]]></tag11> 
<tag11>two</tag11> 
<tag11>three</tag11> 
</tag1> 
<tag1> <tag11><![CDATA[ foo bar 
]]></tag11></tag1> 
<tag1> <tag11><![CDATA[ foo bar]]></tag11></tag1> 
<tag1> <tag11><![CDATA[ foo bar]]></tag11></tag1> 
<tag1> 
<tag11>three</tag11> 
<tag11>four</tag11> 
<tag11>five</tag11> 
<tag11>six</tag11> 
</tag1> 
</whole> 

Dann lief ich den folgenden Code, der seine Ergebnisse am Ende angezeigt.

>>> import os 
>>> os.chdir('c:/scratch') 
>>> from lxml import etree 
>>> context = etree.iterparse('temp.xml') 
>>> for action, elem in context: 
...  print (action, elem.tag, elem.sourceline) 
...  
end tag11 3 
end tag11 4 
end tag11 6 
end tag11 7 
end tag1 2 
end tag11 9 
end tag1 9 
end tag11 11 
end tag1 11 
end tag11 12 
end tag1 12 
end tag11 14 
end tag11 15 
end tag11 16 
end tag11 17 
end tag1 13 
end whole 1 

Kurz gesagt, es scheint nichts mit diesen Zeilen falsch zu sein.

Sie könnten versuchen, die Zeilennummern, in denen Tags gefunden wurden, zu drucken, um die Umgebung des Ortes zu finden, der Probleme in der XML verursacht. (Dies ist eine Bearbeitung basierend auf Wissen, das ich neu auf SO erworben habe.)

Ich würde auch empfehlen, die in der Dokumentation vorgeschlagene Schleifenstruktur zu verwenden, um die Endlosschleife zu vermeiden. Das habe ich in diesem Code gemacht.

+0

Bitte, siehe mein Update. –

+0

FYI: Ich weiß, dass Sie Ihr Problem gelöst haben, aber Sie könnten an der Bearbeitung interessiert sein. –