我正在使用帶有 lxml 的 Python 3.10 來驗證由 VBA 宏生成的 xml 檔案。但在此之前,我必須檢查每個檔案以查看樹的某些部分是否不包含任何文本內容(空白字符除外)以洗掉它們。
例子:
<n4ds:S10_G00_00>
<n4ds:S10_G00_00_001>DGFIP-CAPU</n4ds:S10_G00_00_001>
<n4ds:S10_G00_00_002>CUNOMF001_Janv2021</n4ds:S10_G00_00_002>
<n4ds:S10_G00_00_003>v2022</n4ds:S10_G00_00_003>
<n4ds:S10_G00_00_005>02</n4ds:S10_G00_00_005>
<n4ds:S10_G00_00_006>P21V01</n4ds:S10_G00_00_006>
<n4ds:S10_G00_00_008>01</n4ds:S10_G00_00_008>
<n4ds:S10_G00_01>
<n4ds:S10_G00_01_001>501975304</n4ds:S10_G00_01_001>
<n4ds:S10_G00_01_002>26012</n4ds:S10_G00_01_002>
<n4ds:S10_G00_01_003>NOMINATIF142021</n4ds:S10_G00_01_003>
<n4ds:S10_G00_01_004>Avenue des Champs-Elysees</n4ds:S10_G00_01_004>
<n4ds:S10_G00_01_005>93333</n4ds:S10_G00_01_005>
<n4ds:S10_G00_01_006>BOURBOURG</n4ds:S10_G00_01_006>
<n4ds:S10_G00_01_008>Z</n4ds:S10_G00_01_008>
<n4ds:S10_G00_01_009>APT 25B</n4ds:S10_G00_01_009>
</n4ds:S10_G00_01>
<n4ds:S10_G00_02>
<n4ds:S10_G00_02_001>01</n4ds:S10_G00_02_001>
<n4ds:S10_G00_02_002>Pierre TOPAZE</n4ds:S10_G00_02_002>
<n4ds:S10_G00_02_004>[email protected]</n4ds:S10_G00_02_004>
<n4ds:S10_G00_02_005>0744215264</n4ds:S10_G00_02_005>
</n4ds:S10_G00_02>
<n4ds:S10_G00_95>
<n4ds:S10_G00_95_001>LIART</n4ds:S10_G00_95_001>
<n4ds:S10_G00_95_002>HAM-LES-MOINES</n4ds:S10_G00_95_002>
<n4ds:S10_G00_95_003>50197530426012</n4ds:S10_G00_95_003>
<n4ds:S10_G00_95_006>MtoM</n4ds:S10_G00_95_006>
<n4ds:S10_G00_95_008>20210101091230</n4ds:S10_G00_95_008>
<n4ds:S10_G00_95_900>2101NEORAUB3Message14CollectePH004</n4ds:S10_G00_95_900>
<n4ds:S10_G00_95_901>[email protected]</n4ds:S10_G00_95_901>
</n4ds:S10_G00_95>
<n4ds:S20_G00_05 xsi:type="n4ds:Message_mensuel_des_revenus_autres">
<n4ds:S20_G00_05_001>14</n4ds:S20_G00_05_001>
<n4ds:S20_G00_05_002>01</n4ds:S20_G00_05_002>
<n4ds:S20_G00_05_003>12</n4ds:S20_G00_05_003>
<n4ds:S20_G00_05_004>250319523010</n4ds:S20_G00_05_004>
<n4ds:S20_G00_05_005>2021-01-01</n4ds:S20_G00_05_005>
<n4ds:S20_G00_05_007>2020-12-01</n4ds:S20_G00_05_007>
<n4ds:S20_G00_05_009>IdMed001</n4ds:S20_G00_05_009>
<n4ds:S20_G00_05_010>01</n4ds:S20_G00_05_010>
<n4ds:S20_G00_07>
<n4ds:S20_G00_07_001>VINCENT Tim</n4ds:S20_G00_07_001>
<n4ds:S20_G00_07_002>0102030405</n4ds:S20_G00_07_002>
<n4ds:S20_G00_07_003>[email protected]</n4ds:S20_G00_07_003>
<n4ds:S20_G00_07_004>10</n4ds:S20_G00_07_004>
</n4ds:S20_G00_07>
<n4ds:S20_G00_96>
<n4ds:S20_G00_96_902>4</n4ds:S20_G00_96_902>
</n4ds:S20_G00_96>
<n4ds:S21_G00_06>
<n4ds:S21_G00_06_001>508203890</n4ds:S21_G00_06_001>
<n4ds:S21_G00_06_002>26012</n4ds:S21_G00_06_002>
<n4ds:S21_G00_06_003>5510Z</n4ds:S21_G00_06_003>
<n4ds:S21_G00_06_004>PLACE VENDOME</n4ds:S21_G00_06_004>
<n4ds:S21_G00_06_005>92600</n4ds:S21_G00_06_005>
<n4ds:S21_G00_06_006>ASNIERE</n4ds:S21_G00_06_006>
<n4ds:S21_G00_06_903>CONSEIL PASRAU</n4ds:S21_G00_06_903>
<n4ds:S21_G00_11>
<n4ds:S21_G00_11_001>31284</n4ds:S21_G00_11_001>
<n4ds:S21_G00_11_002>8423Z</n4ds:S21_G00_11_002>
<n4ds:S21_G00_11_003>RUE DU PARADIS</n4ds:S21_G00_11_003>
<n4ds:S21_G00_11_004>75010</n4ds:S21_G00_11_004>
<n4ds:S21_G00_11_005>ALBERVILLE</n4ds:S21_G00_11_005>
<n4ds:S21_G00_11_006>CEDEX 99</n4ds:S21_G00_11_006>
<n4ds:S21_G00_11_111>20210210</n4ds:S21_G00_11_111>
<n4ds:S21_G00_11_904>SRENOMINATIF</n4ds:S21_G00_11_904>
<n4ds:S21_G00_11_905>0</n4ds:S21_G00_11_905>
<n4ds:S21_G00_30>
<n4ds:S21_G00_31></n4ds:S21_G00_31>
<n4ds:S21_G00_47>
<n4ds:S21_G00_48></n4ds:S21_G00_48>
</n4ds:S21_G00_47>
<n4ds:S21_G00_50>
<n4ds:S21_G00_51></n4ds:S21_G00_51>
<n4ds:S21_G00_56></n4ds:S21_G00_56>
</n4ds:S21_G00_50>
<n4ds:S21_G00_97></n4ds:S21_G00_97>
</n4ds:S21_G00_30>
</n4ds:S21_G00_11>
</n4ds:S21_G00_06>
</n4ds:S20_G00_05>
</n4ds:S10_G00_00>
在這種情況下,要驗證我的檔案,我需要洗掉 n4ds:S21_G00_30 和 </n4ds:S21_G00_30> (以及標簽本身)之間的部分。
我試過這段代碼:
pattern = "<n4ds:(.) >(\s)*<\/n4ds:(.) >"
repl = ''
def remove_empty_tags(file, pattern, repl):
clean_lines = []
with open(file, 'r') as fh:
for line in fh:
clean_lines.append(re.sub(pattern, repl, line))
# Now save the file:
with open(file, 'w') as fh:
for line in clean_lines:
fh.write(line)
但是我很難找到正確的正則運算式(將正則運算式與 XML/HTML 一起使用似乎是個壞主意)。就像現在一樣,它不處理嵌套標簽。
我看到我可以使用 ElementTree 決議我的檔案,但我找不到迭代和檢查空樹是否存在的解決方案。
如果有人知道我該如何解決這個問題,我會很高興得到一些幫助。
最好的祝福。
uj5u.com熱心網友回復:
在 XML/HTML 中使用正則運算式似乎是個壞主意
這是一個可怕的想法。
就像現在一樣,它不處理嵌套標簽。
...這就是原因之一。
你說你有lxml。用它。
可以在 XPath 中找到除空白之外沒有文本的元素(即“空白規范化后為空”)normalize-space() = '',而那些沒有子元素的元素則帶有not(*).
在回圈中將它們從各自的父元素中洗掉很容易。
from lxml import etree as ET
tree = ET.parse(r'C:\path\to\your\input.xml')
while True:
empty_nodes = tree.xpath("//*[normalize-space() = '' and not(*)]")
if not empty_nodes:
break
for node in empty_nodes:
node.getparent().remove(node)
tree.write(r'C:\path\to\your\output.xml', pretty_print=True)
話雖如此,由于您在該 VBA 宏中使用 MSXML(對嗎?),并且 MSXML 支持 XPath,因此您可以立即執行完全相同的操作,而無需將 XML 檔案保存為需要后處理的狀態在 Python 中。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/442381.html
