1 回答

TA貢獻1780條經(jīng)驗 獲得超1個贊
我發(fā)現(xiàn)使用lxml更容易完成任務,因為更容易刪除元素。
試試下面的代碼:
from lxml import etree as et
def remove_element(el):
parent = el.getparent()
if el.tail.strip():
prev = el.getprevious()
if prev is not None:
prev.tail = (prev.tail or '') + el.tail
else:
parent.text = (parent.text or '') + el.tail
parent.remove(el)
# Read source XML
parser = et.XMLParser(remove_blank_text=True)
tree = et.parse('Input.xml', parser)
root = tree.getroot()
# Replace the below namespace with your proper one
ns = {'mc': 'http://dummy.com'}
# Processing
for it in root.findall('.//*[@mc:conditions]', ns):
attr = it.attrib
attrTxt = ', '.join([ f'{key}: {value}'
for key, value in attr.items() ])
print(f'Elem.: {et.QName(it).localname:6}: {attrTxt}')
delFlag = False
cond = attr.get('{http://dummy.com}conditions')
if cond:
dct = { k: v for k, v in (x.split('.')
for x in cond.split(',')) }
vn = dct.get('version-number')
st = dct.get('state')
if vn == 'v1-6' and st.startswith('deleted'):
delFlag = True
print(f" {vn}, {st:15} {'Delete' if delFlag else 'Keep'}")
if delFlag:
remove_element(it)
# Print the result
print(et.tostring(tree, method='xml',
encoding='unicode', pretty_print=True))
當然,在目標版本中添加將此樹保存到輸出文件。
為了使用單個根元素正確格式化 XML,我將您的內(nèi)容封裝在:
<main xmlns:MadCap="http://dummy.com">
...
</main>
編輯
在我以前的解決方案中,我曾經(jīng)it.getparent().remove(it)
刪除有問題的元素。但后來我發(fā)現(xiàn)了一個缺陷,如果源 XML 包含“混合內(nèi)容”,即被刪除元素之后的“尾部”文本也被刪除(但它不應該),這個缺陷就會變得可見。
為了防止它,我添加了remove_element函數(shù)以僅刪除元素本身并調(diào)用它而不是以前的it.getparent().remove(it)。
評論中問題后的解釋
attrTxt的來源是attr字典的內(nèi)容(當前元素的屬性)。這個片段實際上打印了這本沒有大括號的字典。它僅用于跟蹤,無處可尋。
另一方面,dct扮演著更重要的角色。它的來源是cond,包含(當前元素的)條件屬性的內(nèi)容,例如state.new-in-vers,version-number.v1-6。
這段代碼:
在逗號上拆分內(nèi)容。
將上述每個部分拆分為一個點。
從這些對創(chuàng)建字典。
然后vn收到版本號 ( v1-6 ) 和st - 狀態(tài) ( new-in-vers )。這是嵌入這里的重要情報。由于這兩個片段可能以不同的順序出現(xiàn),因此您無法創(chuàng)建任何匹配所有可能情況的XPath表達式。但是如果你檢查上面的變量,這個元素是否應該被刪除就變得很明顯了。
添加回答
舉報