簡體   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