2017-04-12 103 views
0

我解析了太大的XML。當一個節點發生故障時,我想繼續循環,並用剩餘的節點做些事情。用無效節點解析XML

版本1

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

與第一個版本,我得到一個例外:

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

所以爲了處理保持節點我已經寫了第二個版本:

版本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 

在這種情況下腳本進入無限循環。

於是,我去具體開行作爲一個文本文件:

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 

我得到:

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> 

所以似乎是行用「\ n」個板缺。這是一個XML錯誤,但爲什麼我的第二個版本不起作用?在我的第二個版本中,行319850和319851作爲XML無效,所以應該傳遞並獲取下一個節點/行。

我在這裏做錯了什麼? 如果你有最好的方法,請讓我知道。

UPDATE

XML文件具有無效字符 '\ X0B'。所以看起來像:

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

CDATA節中的換行符不是XML錯誤。我們如何重現這一點? – mzjn

+0

@mzjn請參閱我的更新 –

+0

例如,請參閱http://stackoverflow.com/questions/20078816/replace-non-ascii-characters-with-a-single-space。 –

回答

0

我已經採取了那些似乎造成麻煩,並塞進試用目的的稍微大一點的xml文件行。就是這個。

<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> 

然後我運行下面的代碼,在結尾處顯示其結果。

>>> 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 

總之,這些行似乎沒有錯。

您可以嘗試打印找到標籤的行號,以便在xml中查找出現問題的位置附近。 (這是一個基於我剛剛在SO上獲得的知識的編輯。)

我也建議使用文檔中建議的循環結構來避免無限循環。這就是我在這段代碼中所做的。

+0

請看我的更新。 –

+0

供參考:我知道你已經解決了你的問題,但你可能對編輯感興趣。 –