我有一些由脚本生成的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>
输出应如下所示:
^{pr2}$我需要移除所有的空元素。您会注意到,我的代码去掉了“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”元素的所有元素都是空的,那么我还想删除它的全部内容。
这意味着,除非您只想硬编码检查一个嵌套级别,否则您需要递归地检查元素及其子元素是否为空。例如:
注意:Python2.5+因为使用了^{} builtin 。在
然后,您可以将代码更改为这样的代码,以删除文档中一直为空的所有元素。在
^{pr2}$样本输出:
您可能需要做的一件事是优化递归函数中的条件} 。在
if e.text:
。目前,它将None
和空字符串视为空,而不是像空格和换行符那样的空白。如果这是“空”定义的一部分,请使用^{编辑:正如@Dave所指出的,可以通过使用generator expression来改进递归函数:
这不会同时为所有子级计算
recursively_empty(c)
,而是惰性地为每个子级计算它。由于all()
将停止对第一个False
元素的迭代,这可能意味着显著的性能改进。在编辑2:可以使用
e.iterchildren()
而不是e.getchildren()
进一步优化表达式。这适用于lxml etree API和objectify API。在相关问题 更多 >
编程相关推荐