【问题标题】:How to replace an element in a tree? (elementtree/markdown)如何替换树中的元素? (元素树/降价)
【发布时间】:2014-01-22 17:56:00
【问题描述】:

如何在元素树的迭代过程中替换元素?我正在为 Markdown 编写一个树处理器,并想包装一个元素。

<pre class='inner'>...</pre>

应该变成

<div class='wrapper'><pre class='inner'>...</pre></div>

我使用getiterator('pre') 来查找元素,但我不知道如何包装它。麻烦点是用新的包装器替换找到的元素,但将现有的元素保留为子元素。

【问题讨论】:

    标签: python elementtree


    【解决方案1】:

    这有点棘手。首先,您需要按照this previous question 中的说明获取父元素。

    parent_map = dict((c, p) for p in tree.getiterator() for c in p)
    

    如果你能得到markdown来使用lxml,这会容易一些——我相信lxml元素已经知道他们的父母了。

    现在,当您从迭代中获取元素时,您还可以获取父元素:

    for elem in list(tree.getiterator('pre')):
        parent = parent_map[elem]
        wrap_elem(parent, elem)
    

    请注意,我已经将迭代器从树变成了一个列表——我们不想在迭代树时修改它。那可能会很麻烦。

    最后,您可以移动元素了:

    def wrap_elem(parent, elem)
        parent_index = list(parent).index(elem)
        parent.remove(elem)
        new_elem = ET.Element('div', attrib={'class': 'wrapper'})
        parent.insert(parent_index, new_elem)
        new_elem.append(elem)
    

    *请注意,我还没有完全测试过这段代码……如果你发现任何错误,请告诉我。

    【讨论】:

    • 这看起来应该可以。尽管我尝试了一种进行双重迭代的变体,但先遍历所有父级,然后遍历子级的内循环。我不希望第二次/以后的传球可能没有设置所有的父母。
    【解决方案2】:

    根据我的经验,你可以使用下面的方法来得到你想要的:
    xml.etree.ElementTree.SubElement(我就叫它ET.Subelementhttp://docs.python.org/2/library/xml.etree.elementtree.html#xml.etree.ElementTree.SubElement

    步骤如下:
    在迭代之前,你应该先获取这些被迭代元素的父元素,并将其存储到变量parent中。

    那么,
    1、将元素&lt;pre class='inner'&gt;...&lt;/pre&gt;存入变量temp

    2、在parent中添加一个新的子元素div

    div = ET.SubElement(parent, 'div')
    

    并设置div的属性:

    div.set('class','wrapper')
    

    3、将步骤1中的元素添加为div的子元素,

    ET.SubElement(div, temp)  
    

    4、删除步骤1中的元素:

    parent.remove(temp)
    

    【讨论】:

      【解决方案3】:

      另一个对我有用的解决方案,类似于 lyfing 的。 将元素复制到临时文件中;用想要的外部标签重新标记原始元素并将其清除,然后将副本附加到原始元素中。

      import copy
      
      temp = copy.deepcopy(elem)
      elem.tag = "div"
      elem.set("class","wrapper")
      elem.clear()
      elem.append(temp)
      

      【讨论】:

        【解决方案4】:

        这样的事情适合一个人:

        for i, element in enumerate(parent):
            if is_the_one_you_want_to_replace(element):
                parent.remove(element)
                parent.insert(i, new_element)
                break
        

        这样的东西适用于许多人:

        replacement_map = {}
        
        for i, element in enumerate(parent):
            if is_an_element_you_want_to_replace(element):
                replacement_map[i] = el_to_remove, el_to_add
        
        for index, (el_to_remove, el_to_add) in replacement_map.items():
            parent.remove(el_to_remove)
            parent.insert(index, el_to_add)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-02-08
          • 2010-11-08
          • 1970-01-01
          • 1970-01-01
          • 2016-04-02
          • 1970-01-01
          • 2016-11-03
          相关资源
          最近更新 更多