Skip to main content
 首页 » 编程设计

python之如何检测python-docx中的空段落

2025年05月04日24sxdcgaq8080

给定一个包含段落的文档

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

我希望以下技术每次都能奏效:

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

或

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

(附带问题,那里有什么区别?似乎 p._p 是 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 元素。任何其他元素,除了书签,无论是直接在段落中还是在运行中,都会使结果非空。

请您参考如下方法:

<w:p>元素可以有大量子元素中的任何一个,正如您从此处的 XML 模式摘录中看到的那样:http://python-docx.readthedocs.io/en/latest/dev/analysis/schema/ct_p.html (参见 CT_P 和 EG_PContent 定义)。

特别是,它经常有一个 w:pPr child,这是样式设置的位置。

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

我倾向于使用 paragraph.text == '' ,它通过运行进行解析。

一个运行可以是空的(文本),所以仅仅存在一个运行是不够的。实际文本保存在 a:t 中(text) 元素,也可以为空。所以 .text方法为您避免了所有这些低级别的复杂性,并且具有作为 API 的一部分的好处,在未来的版本中不太可能改变。