首页 > 解决方案 > 如何通过从底部(运行)到顶部(docDefaults)遍历来获取样式值?

问题描述

TLDR:当我们想在属性中找到值并将其作为输出返回,哪个优先级更高runNone

示例:打印文档中所有运行的字体名称

doc = Document()
for para in doc.paragraphs:
    if para.text:
        for run in para.runs:
            print(run.font.name)

问题:

目前,我正在研究一个用例来检查给定文档是否具有特定的字体/语言/字体大小等,...

例如:为了获取整个文档的语言(拼写和语法)。目前,我按照以下步骤使用以下步骤获取值Style Hierarchy

  1. 加载文档
  2. 遍历段落
  3. 遍历段落的运行
  4. 检查它的(当前运行)rPrlang
  5. 如果运行中没有值,则检查rPr当前参数lang
  6. 如果 para 没有值,则从 para 获取值docDefaults rPr
  7. 如果我在步骤 4-6 之间得到一个值,我会将该值视为运行值

这种方法帮助我获得了 lang 和 font 的预期结果(至少对于我拥有的文档)。

但在某些情况下,它docDefaults本身没有价值,这种方法也无济于事,然后我听说了Style Inheritance

所以我只是实现了一个递归函数来从 中获取值base_style,如果当前样式没有值。

我在我的实现中做了一个小的改变,每当 没有价值时rPr,我只是检查它的base_style价值,然后在层次结构中向上移动一步。

我不确定我遵循的方法是否正确。如果有一个简单的方法来实现这一点。请帮忙。参考

上述步骤的源代码

标签: pythonms-wordpython-docx

解决方案


我认为这里的最终答案只能可靠地来自一组测试用例,这些测试用例基于您可以开发的最少详尽组合,每个测试用例都“手动”确认了它们的预期值应该是什么。

我之所以这么说是因为虽然 .docx 格式的 ISO 规范非常好,但它通常避免指定行为,包括格式/样式继承层次结构的细节。

您似乎走在正确的轨道上,但我会将字符样式添加到您的候选人列表中。例如,运行可以应用显式字体,但也可以应用本身指定字体的字符样式。直接应用于运行的字体将获胜(通过“最近的说明符”原则),但这是一个有趣的问题,它将在运行级别/字符样式和直接应用的段落字体之间获胜。我敢打赌运行级别的字符样式,但这将是您将开发并最初手动验证的测试用例的主题。

我将以下内容作为继承层次结构草案。您可以在 Word 中进行实验时确认并填写位:

  • 直接应用于 run ( run.font)的字符格式
  • 字符样式直接应用于 run ( run.style)
  • 默认运行字符格式直接应用于段落(paragraph.font 注:可能未实现python-docx
  • paragraph.style段落样式 ( )中明确指定的字符格式
  • 按段落样式链接到的字符样式(不确定,也许paragraph.style.character_style
  • 表格样式可以影响某些事情,但也许不会lang。不确定这适合层次结构,这也需要研究和实验。
  • 默认段落样式(可能document.styles["Normal"]但可能是可配置的,并且名称可能会因语言环境而异,例如“Normale”可能是某些语言)
  • 显式文档默认值
  • Word 内置默认值

不确定这是否完全回答了您的问题;如果你需要别的东西,也许你可以澄清一下。


推荐阅读