繁体   English   中英

Python lxml - 如何删除空重复的标记

[英]Python lxml - How to remove empty repeated tags

我有一些由脚本生成的XML,可能有也可能没有空元素。 有人告诉我,现在我们不能在XML中拥有空元素。 这是一个例子:

<customer>  
    <govId>
       <id>@</id>
       <idType>SSN</idType>
           <issueDate/>
           <expireDate/>
           <dob/>
           <state/>
           <county/>
           <country/>
    </govId>
    <govId>
        <id/>
        <idType/>
        <issueDate/>
        <expireDate/>
        <dob/>
        <state/>
        <county/>
        <country/>
    </govId>
</customer>

输出应如下所示:

<customer>  
    <govId>
       <id>@</id>
       <idType>SSN</idType>        
    </govId>        
</customer>

我需要删除所有空元素。 你会注意到我的代码在“govId”子元素中删除了空的东西,但是在第二个元素中没有取出任何东西。 我目前正在使用lxml.objectify。

这基本上就是我在做什么:

root = objectify.fromstring(xml)
for customer in root.customers.iterchildren():
    for e in customer.govId.iterchildren():
        if not e.text:
            customer.govId.remove(e)

有没有人知道用lxml objectify做这个的方法还是有一个更简单的方法期? 如果它的所有元素都是空的,我还想完整地删除第二个“govId”元素。

首先,你的代码的问题在于你是在迭代customers ,而不是在govIds 在第三行,您为每个客户采用第一个 govId ,并迭代其子项。 因此,您需要另一个for循环,以使代码像您希望的那样工作。

在你的问题结尾处的这个小句子然后使问题变得更复杂: 如果所有元素都是空的,我还想完整地删除第二个“govId”元素。

这意味着,除非您想要硬编码只检查一个级别的嵌套,否则需要递归检查元素及其子元素是否为空。 像这样例如:

def recursively_empty(e):
   if e.text:
       return False
   return all((recursively_empty(c) for c in e.iterchildren()))

注意 :Python 2.5+因为使用了all()内置

然后,您可以将代码更改为类似的内容,以删除文档中一直为空的所有元素。

# Walk over all elements in the tree and remove all
# nodes that are recursively empty
context = etree.iterwalk(root)
for action, elem in context:
    parent = elem.getparent()
    if recursively_empty(elem):
        parent.remove(elem)

样本输出:

<customer>
  <govId>
    <id>@</id>
    <idType>SSN</idType>
  </govId>
</customer>

您可能想要做的一件事是在递归函数中改进if e.text:条件。 目前,这将考虑None和空字符串为空,但不是空格和换行符。 如果这是你的“空”定义的一部分,请使用str.strip()


编辑 :正如@Dave所指出的,可以通过使用生成器表达式来改进递归函数:

return all((recursively_empty(c) for c in e.getchildren()))

这不会一次评估所有孩子的recursively_empty(c) ,而是懒惰地为每个孩子评估它。 由于all()将在第一个False元素上停止迭代,这可能意味着显着的性能提升。

编辑2 :使用e.iterchildren()而不是e.getchildren()可以进一步优化表达式。 这适用于lxml etree APIobjectify API

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM