Python lxml XPath解析XML时如何获取p标签父div的n属性
lxml获取匹配节点父属性的实现方法
问题场景
使用lxml解析XML时,通过XPath匹配到div下的目标p标签后,需要同时获取p标签的完整内容、以及其所属div的n属性,原有遍历逻辑仅能访问p标签自身属性,无法直接拿到父节点信息。
可用实现方案
方案1:调用元素原生getparent()方法获取父节点
lxml的元素对象自带getparent()方法,可直接返回当前元素的直接父节点,适合层级固定的场景:
from lxml import etree mystring='''<div n="0001" type="doc" xml:id="_3168060002"> <p xml:id="_3168060003">[car 1] Séquence préparatoire pour <p xml:id="_3168060005">a) la définition </p></p></p></div> <div n="0002" type="doc" xml:id="_3168060012"><p xml:id="_3168060003">[blue] la voiture pour <p xml:id="_3168060005">a) la définition </p></p></p></div> ''' parser = etree.XMLParser(resolve_entities=False, strip_cdata=False, recover=True, ns_clean=True) # 多同级div需要补根节点,若原XML已有外层根可省略该步骤 xml_content = f"<root>{mystring}</root>" XML_tree = etree.fromstring(xml_content.encode(), parser=parser) all_paras = XML_tree.xpath('.//div[@n]/p[@xml:id]') for para in all_paras: # 获取直接父节点 parent_div = para.getparent() # 读取父节点n属性 div_n = parent_div.get('n') # 递归提取p标签下所有文本(兼容嵌套子标签) para_content = ''.join(para.itertext()).strip() print(f"div n属性:{div_n}") print(f"p标签内容:{para_content}") print("---")
如果p和目标div之间存在不确定层数的嵌套,可以用XPath找最近的祖先div节点,避免层级变动导致取错父节点:
# 查找距离当前p最近、带n属性的div祖先 parent_div = para.xpath('./ancestor::div[@n][1]')[0]
方案2:调整XPath语句一次性返回所有目标数据
直接在XPath中同时选取p节点和对应父节点的n属性,查询结果会自动配对返回,省去单独取父节点的步骤:
# XPath语法中..代表当前节点的父级,查询结果返回( p元素, 对应div的n属性 )元组 all_paras = XML_tree.xpath('.//div[@n]/p[@xml:id]/(., ../@n)') for para, div_n in all_paras: para_content = ''.join(para.itertext()).strip() print(f"div n属性:{div_n}") print(f"p标签内容:{para_content}") print("---")
注意事项
- 不要用
para.text提取p标签内容,该属性仅能获取p标签直接包裹的文本,无法读取嵌套子标签内的文本,itertext()方法会递归遍历所有子节点拼接完整文本,适配嵌套场景。 - 合法XML要求单一根节点,如果你的XML内容是多个div平级的结构,直接传入
etree.fromstring()会触发解析错误,可参考示例在外层包裹一层临时根节点,若原数据本身已有外层根节点可跳过该操作。
内容的提问来源于stack exchange,提问作者JFerro
相关产品推荐
相关产品推荐

