1
votes

TLDR: Which takes higher precedence Style Inheritance or Style Hierarchy, when we want to find value in the run properties and it gives back None as the output.?

Example: Printing the font name from all the runs in the document

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

Problem:

Currently, I'm working on a use-case to check whether the given document has a specific font/language/font size, etc,...

For example: In order to get the language (spelling and grammar) for the entire document. Currently, I follow the below steps to get values using Style Hierarchy:

  1. Load the document
  2. Iterate through paragraphs
  3. Iterate through the runs of a paragraph
  4. Check it's(current run) rPr for lang
  5. If there is no value from run, then check the rPr of the current para for lang
  6. If there is no value from para, then get value from docDefaults rPr
  7. If I get a value between Step 4-6, I'll consider that value as run's value

This approach helped me to get the expected result for both lang and font (at least for the document I have).

But for some cases, the docDefaults itself won't have a value and this approach doesn't help, then I heard about Style Inheritance.

So I just implemented a recursive function to get the value from the base_style, if the current style doesn't have a value.

I made a minor change in my implementation as, Whenever there is no value from the rPr, I just check it's base_style for value, before moving one step up in the hierarchy.

I'm not sure whether the approach I'm following is correct. If there is an easy way to achieve this. Please help. References

Source Code for the above steps

1

1 Answers

1
votes

I think the final answer here can only reliably come from a set of test cases that are based on the minimum set of exhaustive combinations you can develop, each confirmed "by hand" as to what their expected value should be.

The reason I say this is because although the ISO spec for the .docx format is quite good, it generally avoids specifying behaviors, including the specifics of the formatting/style inheritance hierarchy.

You seem to be on the right track, but I would add character styles to your list of candidates. For example, a run can have an explicit typeface applied, but it can also have a character-style applied that itself specifies a typeface. A typeface directly-applied to the run would win (by the "nearest specifier" principle), but it's an interesting question which would win between a run-level/character style and a directly-applied paragraph typeface. I'd bet on the run-level character-style, but such would be the subject of the test cases you would develop and initially verify by hand.

I would take the following as a draft inheritance hierarchy. You can confirm and fill in bits as you experiment in Word:

  • character-formatting directly applied to run (run.font)
  • character-style directly applied to run (run.style)
  • default run character formatting directly applied to paragraph (paragraph.font Note: may not be implemented in python-docx)
  • character formatting explicitly specified in paragraph style (paragraph.style)
  • character-style linked-to by paragraph style (not sure, maybe paragraph.style.character_style)
  • a table-style can affect certain things, but maybe not lang. Not sure where that fits into hierarchy, that would require research and probably experimentation too.
  • default paragraph style (probably document.styles["Normal"] but may be configurable and names might possibly vary with locale, like maybe "Normale" is some languages)
  • explicit document default
  • Word built-in default

Not sure if this completely answers your question; perhaps you can clarify it if you need something else.