我有大量嵌套结构的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)
,但它也不起作用,它最后添加了元素,我得到了无限循环。
任何有用的帮助。
答案 0 :(得分:2)
这里要提几点:
首先,如果您使用element.text is not None
解析上面给出的XML文件,则您的测试True
始终会返回xml.etree.Elementree
,因为在每个节点的末尾都有一个换行符,因此,每个所谓的无文本节点中的文本始终具有\n
个字符。另一种方法是使用lxml.etree.parse
和lxml.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因为我打印出的树很难用肉眼阅读。