2017-04-12 95 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

供参考:我知道你已经解决了你的问题,但你可能对编辑感兴趣。 –