1 回答
TA贡献1780条经验 获得超1个赞
我发现使用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,我将您的内容封装在:
<main xmlns:MadCap="http://dummy.com">
...
</main>
编辑
在我以前的解决方案中,我曾经it.getparent().remove(it)
删除有问题的元素。但后来我发现了一个缺陷,如果源 XML 包含“混合内容”,即被删除元素之后的“尾部”文本也被删除(但它不应该),这个缺陷就会变得可见。
为了防止它,我添加了remove_element函数以仅删除元素本身并调用它而不是以前的it.getparent().remove(it)。
评论中问题后的解释
attrTxt的来源是attr字典的内容(当前元素的属性)。这个片段实际上打印了这本没有大括号的字典。它仅用于跟踪,无处可寻。
另一方面,dct扮演着更重要的角色。它的来源是cond,包含(当前元素的)条件属性的内容,例如state.new-in-vers,version-number.v1-6。
这段代码:
在逗号上拆分内容。
将上述每个部分拆分为一个点。
从这些对创建字典。
然后vn收到版本号 ( v1-6 ) 和st - 状态 ( new-in-vers )。这是嵌入这里的重要情报。由于这两个片段可能以不同的顺序出现,因此您无法创建任何匹配所有可能情况的XPath表达式。但是如果你检查上面的变量,这个元素是否应该被删除就变得很明显了。
添加回答
举报