我想清理我的xml,这样它不仅是有效的XML,而且还以一种非常人性化的方式进行格式化。例如:
<Items>
<Name>Hello</Name>
<Cost>9.99</Cost>
<Condition/>
</Items>
我想删除任何带有空标记的行,并留下:
<Items>
<Name>Hello</Name>
<Cost>9.99</Cost>
</Items>
我尝试使用正则表达式进行此操作,但在将其保留为可读格式方面没有多少运气:
txt = etree.tostring(self.xml_node, pretty_print=True)
txt = re.sub(r'<[a-zA-Z]+/>\n', '', txt)
实现上述目标的最佳方法是什么?
答案 0 :(得分:5)
使用 XML解析器。
我的想法是find all empty nodes //*[not(node())]
XPath表达式和remove them from the tree。例如,使用lxml
:
from lxml import etree
data = """
<Items>
<Name>Hello</Name>
<Cost>9.99</Cost>
<Condition/>
</Items>
"""
root = etree.fromstring(data)
for element in root.xpath(".//*[not(node())]"):
element.getparent().remove(element)
print etree.tostring(root, pretty_print=True)
答案 1 :(得分:0)
可以将此解决方案考虑为XML数据的第n级深度。
from lxml import etree
def recursively_empty(xml_element):
if xml_element.text:
return False
return all((recursively_empty(xe) for xe in xml_element.iterchildren()))
data = """
<Items>
<Name>Hello</Name>
<Cost>9.99</Cost>
<Condition/>
</Items>
"""
xml_root = etree.iterwalk(data)
for action, xml_element in xml_root:
parent = xml_element.getparent()
if recursively_empty(xml_element):
parent.remove(xml_element)
请注意:使用递归方法的原因是为了解决多层次的XML数据深度。
解决方案应该适用于各种深度
data1 = """
<Items>
<Name>Hello</Name>
<Cost>9.99</Cost>
<Condition/>
</Items>
"""
data2 = """
<Items>
<Name>Hello</Name>
<Cost>9.99</Cost>
<Condition>
<cond1>Somedata</cond1>
</Condition>
</Items>
"""
data3 = """
<Items>
<Name>Hello</Name>
<Cost>9.99</Cost>
<Condition>
</cond1>
</Condition>
</Items>
"""