如何在python-docx中检测空段

时间:2018-07-06 20:20:05

标签: python python-docx

给出包含段落的文档

d = docx.Document()
p = d.add_paragraph()

我希望每次都能使用以下技术:

if len(p._element) == 0:
    # p is empty

OR

if len(p._p) == 0:
    # p is empty

(另一个问题,有什么区别?似乎在每种情况下我都在野外见过p._p is p._element。)

如果我在段落中添加样式,则检查将不再起作用:

>>> p2 = d.add_paragraph(style="Normal")
>>> print(len(p2._element))
1

显式设置text=None也无济于事,不是我期望的那样。

那么如何检查段落是否没有内容(特别是文本和图像,尽管一般性更好)?

更新

我弄乱了一点,发现设置样式显然增加了一个pPr元素:

>>> p2._element.getchildren()
[<CT_PPr '<w:pPr>' at 0x7fc9a2b64548>]

元素本身为空:

>>> len(p2._element.getchildren()[0])
0

但更重要的是,这不是奔跑。

所以我的测试现在看起来像这样:

def isempty(par):
    return sum(len(run) for run in par._element.xpath('w:r')) == 0

我对底层系统了解不足,无法知道这是否是一个合理的解决方案,以及警告。

更多更新

似乎我需要能够处理一些不同的情况:

def isempty(par):
    p = par._p
    runs = p.xpath('./w:r[./*[not(self::w:rPr)]]')
    others = p.xpath('./*[not(self::w:pPr) and not(self::w:r)] and '
                     'not(contains(local-name(), "bookmark"))')
    return len(runs) + len(others) == 0

这会跳过所有w:pPr元素,并且只运行w:rPr元素。除了书签外,任何其他元素(无论是直接在段落中还是在段落中)都将使结果为非空。

1 个答案:

答案 0 :(得分:4)

<w:p>元素可以具有大量子元素,如您从XML模式摘录中看到的:http://python-docx.readthedocs.io/en/latest/dev/analysis/schema/ct_p.html(请参阅CT_P和EG_PContent定义)。

尤其是,它通常有一个w:pPr子级,这是样式设置所在的位置。

因此,对于误报(如果为空则认为是肯定的),您的测试不是很可靠。

我倾向于使用paragraph.text == '',它会分析运行。

运行可以为空(文本),因此仅运行就不足以证明。实际文本保存在a:t(文本)元素中,该元素也可以为空。因此,.text方法为您避免了所有这些低级复杂性,并具有成为API的一部分的好处,因此在将来的版本中更改的可能性很小。