Python Lxml:添加和删除标签

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

我正在尝试在一个xml树中添加和删除标签(下面有个简短的示例)。我有一个布尔值的字典,用来决定是否添加或删除某个标签。如果值是true,并且这个元素不存在,就会创建这个标签(如果它的父标签也不存在的话,也会一起创建)。如果值是false,就会删除这个标签。

不过,这似乎没有效果,我找不到原因。

<Assets>
  <asset name="Adham">
    <pos>
      <x>27913.769923</x>
      <y>5174.627773</y>
    </pos>
    <GFX>
      <space>P03.png</space>
      <exterior>snow.png</exterior>
    </GFX>
    <presence>
      <faction>Dvaered</faction>
      <value>10.000000</value>
      <range>1</range>
    </presence>
    <general>
      <class>P</class>
      <population>100</population>
      <services>
        <land/>
        <refuel/>
      </services>
      <commodities/>
      <description>Fooo</description>
      <bar>(null)</bar>
    </general>
  </asset>
</Assets>

代码:

def writeflagX(self, root, x_path, _flag): 
    ''' Writes flag to tree: deletes if false and already exists
    and adds if true but doesn't exist yet)
    '''
    try:
        if root.xpath(x_path):
            if not self.flag[_flag]: 
                #delete value
                temp1 = root.xpath(x_path)
                temp1.getparent().remove(temp1)
                print "removed"
                #yeah, pretty ugly
    except AttributeError:
        #element does not exist, so create it if true value is here
        #first, see if parent tag of list items exists, create it if neccesary
        #split xpath into leader and item
        leader = x_path.split("/")[0]
        print leader
        item = x_path.split("/")[1]
        try:
            if root.xpath(leader): #try to see if parent tag exists
                child = etree.Subelement(root.xpath(leader), item)
                print "no errors"
            print "not caught"
        except AttributeError:
            l2 = leader.split("/")[0]
            print l2 + " hi"
            try:
                l3 = leader.split("/")[1]
                if  l3: #if this tag is not a direct child of the root 
                    child1 = etree.Subelement(root.xpath(l2), l3)
                    child1.append(etree.Element(item))
                    print "no dex error"
            except IndexError: #if this tag is a direct child of the root
                print "dex error"
                child2 = etree.SubElement(root, l2)

def writeALLflagsX(self, _root):
    '''Uses writeflagX and sets all the flags
    '''
    for k in self.flag:
        self.writeflagX(_root, self.flagPaths[k], k)

我试着把任务的标志从false改成true,把加油的标志从true改成false。

#Change Missions to true and refuel to false

foo = Asset()
###parsing code###
foo.alist["Adham"].flag["Is_missions"] = True
foo.alist["Adham"].flag["Is_refuel"] = False
foo.alist["Adham"].writeALLflagsX(foo.alist["Adham"].node)

foo.writeXML("output.xml")

我很困惑。任务标签没有被添加,加油标签也没有被删除。

这是不是跟我把try/except语句嵌套在一起有关呢?

编辑:
好吧,按照建议用for循环解决了删除的问题:

temp1 = root.xpath(x_path)
                    for n in temp1:
                        n.getparent().remove(n)

但我还是无法添加一个节点。

我想我会提出一个更简单的新问题,因为这个问题太复杂了。

编辑编辑:新的问题要简单得多:如何使用xpath添加元素及其父元素

1 个回答

2

代码中有几个地方可以改进:

  • node.xpath 返回的是节点列表,也就是说你不能直接用 root.xpath(path).getparent()。你需要先检查这个列表,如果你确定第一个节点应该存在,就取列表中的第一个节点(你的节点删除代码是这样用的);
  • 在处理属性的时候,可以试试用 node.attrib 这个字典。处理属性就像修改 Python 字典一样简单(比如 del node.attrib[attr] 删除属性,node.attrib[attr] = value 设置属性,记得 value 要是字符串类型);
  • 使用 etree.XML('<myelement><child/></myelement>') 来创建新节点可能会很有用。

希望这些建议对你有帮助。

撰写回答