如何用Python提取仅含键名、无模板URL的XML XPath
解决方案:基于lxml提取简洁XPath与对应值
核心思路
- 移除XML命名空间前缀,避免XPath中出现冗长的命名空间URL
- 递归遍历所有节点,构建仅包含元素名的层级路径
- 统一处理空文本/无文本节点,返回
None而非空白字符 - 清理XML中的冗余空白,避免干扰文本值判断
代码实现
from lxml import etree def extract_clean_xpaths(xml_content): # 解析XML时自动移除空白文本节点 parser = etree.XMLParser(remove_blank_text=True) tree = etree.fromstring(xml_content, parser) # 遍历所有节点,剥离命名空间前缀 for elem in tree.iter(): if elem.tag.startswith('{'): elem.tag = elem.tag.split('}', 1)[1] result = [] def traverse(node, current_path): # 处理节点文本:非空则去首尾空白,空值转为None node_text = node.text.strip() if node.text else None if node_text == '': node_text = None # 根节点路径为空字符串,可根据需求过滤 if current_path: result.append((current_path, node_text)) # 递归遍历子节点,拼接路径 for child in node: child_path = f"{current_path}/{child.tag}" if current_path else child.tag traverse(child, child_path) traverse(tree, '') return result # 测试用带命名空间的XML test_xml = """ <root xmlns="http://example.com/ns"> <language> <terminology_id> <value>ISO_639-1</value> </terminology_id> <code_string>xx</code_string> </language> <territory> <terminology_id> <value>ISO_3166-1</value> </terminology_id> </territory> </root> """ # 执行并输出结果 print(extract_clean_xpaths(test_xml))
代码说明
- 命名空间处理:将带命名空间的标签(如
{http://example.com/ns}language)直接转换为纯标签名language,避免路径中出现命名空间URL - 空白清理:解析XML时启用
remove_blank_text=True,同时对节点文本做strip()处理,彻底消除\n\t\t这类冗余空白 - 路径构建:通过递归遍历,拼接父节点路径与当前节点名,生成类似
language/terminology_id/value的简洁路径 - 空值统一:无文本或文本为空的节点,统一返回
None,完全匹配需求示例格式
输出结果
运行代码后将得到与需求一致的结果:
[('language/terminology_id/value', 'ISO_639-1'), ('language/terminology_id', None), ('language/code_string', 'xx'), ('language', None), ('territory/terminology_id/value', 'ISO_3166-1'), ('territory/terminology_id', None), ('territory', None)]
内容的提问来源于stack exchange,提问作者Poe Dator
相关产品推荐
相关产品推荐

