过滤xml文件以删除包含特定文本的行?

时间:2011-07-03 20:22:33

标签: python html xml xpath lxml

例如,假设我有:

<div class="info"><p><b>Orange</b>, <b>One</b>, ...
<div class="info"><p><b>Blue</b>, <b>Two</b>, ...
<div class="info"><p><b>Red</b>, <b>Three</b>, ...
<div class="info"><p><b>Yellow</b>, <b>Four</b>, ...

我想删除列表中包含单词的所有行,因此我只会在符合条件的行上使用xpath。例如,我可以使用列表['Orange', 'Red']来标记不需要的行,因此在上面的示例中,我只想使用第2行和第4行进行进一步处理。

我该怎么做?

2 个答案:

答案 0 :(得分:1)

使用

//div
  [not(p/b[contains('|Orange|Red|', 
                    concat('|', ., '|')
                   )
          ]
       )
  ]

这将选择XML文档中的任何div元素,使其没有p子元素,其b子元素的字符串值是以管道分隔的字符串列表中的字符串之一用作过滤器。

这种方法只需在管道分隔列表中添加新的过滤器值即可实现可扩展性,而无需更改XPath表达式中的任何其他内容。

注意:当静态知道XML文档的结构时,请始终避免使用// XPath伪运算符,因为它会导致显着的低效率(减速)。

答案 1 :(得分:0)

import lxml.html as lh

# http://lxml.de/xpathxslt.html
# http://exslt.org/regexp/functions/match/index.html
content='''\
<table>
<div class="info"><p><b>Orange</b>, <b>One</b></p></div>
<div class="info"><p><b>Blue</b>, <b>Two</b></p></div>
<div class="info"><p><b>Red</b>, <b>Three</b></p></div>
<div class="info"><p><b>Yellow</b>, <b>Four</b></p></div>
</table>
'''
NS = 'http://exslt.org/regular-expressions'
tree = lh.fromstring(content)
exclude=['Orange','Red']
for elt in tree.xpath(
    "//div[not(re:test(p/b[1]/text(), '{0}'))]".format('|'.join(exclude)),
    namespaces={'re': NS}):
    print(lh.tostring(elt))
    print('-'*80)

产量

<div class="info"><p><b>Blue</b>, <b>Two</b></p></div>

--------------------------------------------------------------------------------
<div class="info"><p><b>Yellow</b>, <b>Four</b></p></div>

--------------------------------------------------------------------------------