lxml过滤子标记之间没有文本的HTML标记

时间:2014-03-06 23:16:06

标签: python lxml

我有一些像这样的文件

....
  <tag1>
     <tag2>Foo</tag2>
     <tag3>Bar</tag3>
  </tag1>

  <tag1>
     <tag2>Foo</tag2>
     <tag3>Bar</tag3>
     Foo
  </tag1>

  <tag1>
     <tag2>Foo</tag2>     
     Foo
     <tag3>Bar</tag3>
  </tag1>

  <tag1>
     Foo
  </tag1>
 ....

我想过滤只有子标签的标签,即不要在子标签之间放置一些文字。如果是上述情况,则应返回第一个<tag1>

我的代码最初是

from lxml import html

html_content = html.fromstring(content)
tag1 = html_content.xpath('//tag1')
tags = []
for tag in tag1:
   exists = False
   for child in tag.getchildren():
      exists = exists or (len(child.tag) == 0)
   if (not exists):
      tags.append(tag)

但结果是getchildren()没有返回不在任何标记之间的文本。怎么做?

2 个答案:

答案 0 :(得分:2)

使用代码的.tail attribute

for tag in tag1:
    exists = False
    for child in tag.getchildren():
        exists = exists or not child.tail.strip()
    if not exists:
        tags.append(tag)

根据“只有孩子的标签”的含义,这相当于:

for tag in tag1:
  children = tag.getchildren()
  no_extra_text = not any(child.tail.strip() for child in children)
  if children and no_extra_text:
    tags.append(tag)

这是一个更新,包括检查前导文本并在文本为None时删除错误(我认为它总是一个字符串):

for tag in tag1:
  children = tag.getchildren()
  no_extra_text = not any(child.tail and child.tail.strip() for child in children)
  no_text = tag.text and not tag.text.strip()
  if children and no_extra_text and no_text:
    tags.append(tag)

答案 1 :(得分:2)

getchildren()做什么方法

  

返回所有直接子节点。元素按文档顺序返回。

所以getchildren()返回节点。每个节点都有属性:

根据您的要求,答案是tail,它将为您提供

  

在此元素的结束标记之后但在下一个兄弟元素的开始标记之前的文本。如果没有文本,则为字符串或值None。