如何使用python使嵌套的xml结构平坦

时间:2016-10-18 11:19:08

标签: python xml

我有大量嵌套结构的XML。 喜欢这个

<root>
 <node1>
  <subnode1>
    <name1>text1</name1>
  </subnode1>
 </node1>
 <node2>
  <subnode2>
     <name2>text2</name2>
  </subnode2>
 </node2>
</root>

我想将其转换为

<root>
  <node1>
    <name1>text1</name1>
  </node1>
  <node2>
    <name2>text2</name2>
  </node2>
</root>

我尝试了以下步骤

from xml.etree import ElementTree as et

tr = etree.parse(path)
root = tr.getroot()

for node in root.getchildren():
  for element in node.iter():
    if (element.text is not None):
      node.extend(element) 

我也尝试过使用node.append(element),但它也不起作用,它最后添加了元素,我得到了无限循环。 任何有用的帮助。

1 个答案:

答案 0 :(得分:2)

这里要提几点:

首先,如果您使用element.text is not None解析上面给出的XML文件,则您的测试True始终会返回xml.etree.Elementree,因为在每个节点的末尾都有一个换行符,因此,每个所谓的无文本节点中的文本始终具有\n个字符。另一种方法是使用lxml.etree.parselxml.etree.XMLParser忽略空白文本,如下所示。

其次,在阅读它时附加到树上是不好的。这个代码为什么会给出无限循环的原因相同:

>>> a = [1,2,3,4]
>>> for k in a:
        a.append(5)

你可以在这里看到@Alex Martelli对这个问题的回答:Modifying list while iterating关于这个问题。

因此,您应该创建一个缓冲区 XML树并相应地构建它,而不是在遍历它时修改树。

from xml.etree import ElementTree as et
import pdb;

from lxml import etree

p = etree.XMLParser(remove_blank_text=True)
path = 'test.xml'
tr = et.parse(path, parser = p)
root = tr.getroot()

buffer = et.Element(root.tag);

for node in root.getchildren():
    bnode = et.Element(node.tag)
    for element in node.iter():
        #pdb.set_trace()
        if (element.text is not None):
            bnode.append(element)
            #node.extend(element)
    buffer.append(bnode)

et.dump(buffer)

示例运行和结果:

Chip chip@ 01:01:53@ ~: python stackoverflow.py
<root><node1><name1>text1</name1></node1><node2><name2>text2</name2></node2></root>

注意:您可以随时尝试使用python中的lxml包来打印漂亮的XML树,如下所示:Pretty printing XML in Python因为我打印出的树很难用肉眼阅读。