如何通过xpath添加元素及其父元素

4 投票
1 回答
2924 浏览
提问于 2025-04-16 15:06

好的,我有一个情况需要根据一个xpath给某个标签添加一个新标签。

下面是一个示例xml:

<?xml version="1.0" encoding="UTF-8"?>
<Assets>
 <asset name="Adham">
  <general>>
   <services>
    <land/>
    <refuel/>
   </services>
  </general>
 </asset>
 <asset name="Test">
  <general>
   <Something/>
  </general>
 </asset>
</Assets>

我想给两个资产都添加一个 <missions> 标签。不过,第二个资产缺少父标签 <services>,我也想添加这个标签。每个资产标签都存储在一个变量里(比如叫 node1 和 node2)。

我有一个xpath: xpath1 = services/missions,因为我的程序工作方式的原因,我不能简单地以其他形式存储它(也就是说,我没有地方单独存储 services)。

我需要检查一下 <missions> 标签是否已经存在,如果存在就不做任何事情。如果标签不存在,我需要创建它。如果它的父标签不存在,我也需要创建它。

我该如何仅通过这个xpath字符串来做到这一点呢?

编辑:我想基于一个布尔值来做这件事:也就是说,如果 val = true,那么在必要时创建标签(和父标签)。如果是 false,就删除标签。

(我没有其他方法来引用我需要的标签,因为我有很多层的函数来自动化这个过程,你可以查看我之前的问题 Python Lxml: Adding and deleting tags)。

编辑编辑:还有一个问题:

我没有一个变量来包含要添加元素的父标签,只有一个变量包含 <asset> 对象。我正在尝试使用xpath和一个指向 <asset> 标签的变量来获取我想要的节点的父标签。

编辑编辑编辑:算了,以上的问题我会通过缩短xpath来指向父标签,并使用变量名来引用每个项目来解决。

1 个回答

2
def to_xml(parent, xpath, value):
    """
    parent: lxml.etree.Element
    xpath: string like 'x/y/z', anything more complex is likely to break
    value: anything, if is False - means delete node
    """        
    # find the node to proceed further        
    nodes = parent.xpath(xpath)        
    if nodes:
        node = nodes[0]
    else:
        parts = xpath.split('/')
        p = parent
        for part in parts:
            nodes = p.xpath(part)
            if not nodes:
                n = etree.XML("<%s/>" % part)
                p.append(n)
                p = n
            else:
                p = nodes[0]
        node = p
    # do whatever is specified vy value
    if value is False:
        node.getparent().remove(node)
    else:
        node.text = str(value)

虽然我不太确定把添加和删除的功能放在一个函数里是不是个好主意,但无论如何,这样做可能会像你想的那样有效。

撰写回答