从XML文档中有条件地删除元素

2024-07-06 21:51:31 发布

您现在位置:Python中文网/ 问答频道 /正文

我的任务是对python3中XML树的一些元素进行小的重构,即替换以下结构:

<span class="nobr">
 <a href="http://www.google.com/">
  http://www.google.com/
  <sup>
   <img align="absmiddle" alt="" border="0" class="rendericon" height="7" src="http://jira.atlassian.com/icon.gif" width="7"/>
  </sup>
 </a>
</span>

有:

^{pr2}$

即,如果整个结构与第一个示例中给出的结构完全对应,则删除sup元素。我需要在处理过程中保留XML文档,所以regexp匹配在某种程度上是不可能的。在

我已经有了适用于我目的的代码:

doc = self.__refactor_links(doc)
...
def __refactor_links(self, node):
    """Recursively seeks for links to refactor them"""
    for span in node.childNodes:
        replace = False
        if isinstance(span, xml.dom.minidom.Element):
            if span.tagName == "span" and span.getAttribute("class") == "nobr":
                if span.childNodes.length == 1:
                    a = span.childNodes.item(0)
                    if isinstance(a, xml.dom.minidom.Element):
                        if a.tagName == "a" and a.getAttribute("href"):
                            if a.childNodes.length == 2:
                                aurl = a.childNodes.item(0)
                                if isinstance(aurl, xml.dom.minidom.Text):
                                    sup = a.childNodes.item(1)
                                    if isinstance(sup, xml.dom.minidom.Element):
                                        if sup.tagName == "sup":
                                            if sup.childNodes.length == 1:
                                                img = sup.childNodes.item(0)
                                                if isinstance(img, xml.dom.minidom.Element):
                                                    if img.tagName == "img" and img.getAttribute("class") == "rendericon":
                                                        replace = True
            else:
                self.__refactor_links(span)
        if replace:
            a.removeChild(sup)
    return node

这个不会递归地遍历所有的标记-如果它与它所寻找的结构相匹配-即使它失败了,它也不会继续在这些元素中寻找结构,但在我的例子中,我不应该这样做(虽然这样做也很好,但在我看来,添加一堆else:self.\uu-refactor\u-links(tag)的成本会让它消失。在

如果任何条件失败,则不应执行任何移除操作。有没有更干净的方法来定义一组条件,避免大量的“如果”?一些自定义数据结构可以用来存储条件,例如('sup',('img',(…)),但我不知道应该如何处理它。如果你有任何建议或例子在python-请帮助。在

谢谢。在


Tags: selfimgifxmlelementlinks结构dom
3条回答

这里有一个关于lxml的快速操作。强烈推荐xpath。在

>>> from lxml import etree
>>> doc = etree.XML("""<span class="nobr">
...  <a href="http://www.google.com/">
...   http://www.google.com/
...   <sup>
...    <img align="absmiddle" alt="" border="0" class="rendericon" height="7" src="http://jira.atlassian.com/icon.gif" width="7"/>
...   </sup>
...  </a>
... </span>""")
>>> for a in doc.xpath('//span[@class="nobr"]/a[@href="http://www.google.com/"]'):
...     for sub in list(a):
...         a.remove(sub)
...
>>> print etree.tostring(doc,pretty_print=True)
<span class="nobr">
 <a href="http://www.google.com/">
  http://www.google.com/
  </a>
</span>

我不擅长xml,但是你不能在节点上使用find/search吗

>>> from xml.dom.minidom import parse, parseString
>>> dom = parseString(x)
>>> k = dom.getElementsByTagName('sup')
>>> for l in k:
...     p = l.parentNode
...     p.removeChild(l)
... 
<DOM Element: sup at 0x100587d40>
>>> 
>>> print dom.toxml()
<?xml version="1.0" ?><span class="nobr">
 <a href="http://www.google.com/">
  http://www.google.com/

 </a>
</span>
>>> 

这绝对是XPath表达式的任务,在您的例子中可能与lxml结合使用。在

XPath可能是这样的:

//span[@class="nobr"]/a[@href]/sup[img/@class="rendericon"]

将树与此XPath表达式匹配,并删除所有匹配的元素。 不需要无休止的if构造或递归。在

相关问题 更多 >