Loading...
Loading...
Use when python-docx paragraphs created via OxmlElement ignore the intended style or fall back to Normal - explains the style-name vs style-ID mismatch, shows the fix, and notes the related section-break removal pitfall.
npx skill4agent add hubeiqiao/tim-project-skills python-docx-style-id-mismatchpython-docxNormalUse $python-docx-style-id-mismatch to fix why my Heading 2 paragraphs render as Normal.Use $python-docx-style-id-mismatch to explain the difference between style names and style IDs in python-docx.Use $python-docx-style-id-mismatch to review this OxmlElement paragraph insertion code.OxmlElementw:pStyleOxmlElement('w:p')doc.add_paragraph()pStyle.set(qn('w:val'), 'Heading 2')paragraph.style.namestyle.namestyle.style_iddoc.add_paragraph(style='Heading 2')OxmlElementw:pStyleSTYLE_ID_MAP = {
'Normal': 'Normal',
'Heading 1': 'Heading1',
'Heading 2': 'Heading2',
'Heading 3': 'Heading3',
'Heading 4': 'Heading4',
'List Bullet': 'ListBullet',
'List Number': 'ListNumber',
'Caption': 'Caption',
'table of figures': 'TableofFigures',
'Body Text': 'BodyText',
'First Paragraph': 'FirstParagraph',
'Compact': 'Compact',
}
def get_style_id(style_name):
"""Convert a style display name to its XML style ID."""
return STYLE_ID_MAP.get(style_name, style_name.replace(' ', ''))# WRONG - silent failure, falls back to Normal
pStyle.set(qn('w:val'), 'Heading 2')
# CORRECT - uses XML style ID
pStyle.set(qn('w:val'), get_style_id('Heading 2')) # -> 'Heading2'style_name.replace(' ', '')for i, p in enumerate(doc.paragraphs):
if p.style.name.startswith('Heading'):
print(f"[{i}] style.name='{p.style.name}' text='{p.text[:60]}'")for style in doc.styles:
if style.name.startswith('Heading'):
print(f"Display: '{style.name}' -> ID: '{style.style_id}'")body.remove(element)w:sectPrw:pPr# Check sections
print(f"Sections: {len(doc.sections)}")
# Re-add section break before a target paragraph
prev_para = doc.paragraphs[target_idx - 1]
prev_pPr = prev_para._element.get_or_add_pPr()
sectPr = OxmlElement('w:sectPr')
# ... configure sectPr properties ...
prev_pPr.append(sectPr)from docx.oxml import OxmlElement
from docx.oxml.ns import qn
def create_heading(doc, ref_element, text, level=2):
p = OxmlElement('w:p')
pPr = OxmlElement('w:pPr')
pStyle = OxmlElement('w:pStyle')
# Key line: use get_style_id, not raw display name
pStyle.set(qn('w:val'), get_style_id(f'Heading {level}'))
pPr.append(pStyle)
p.append(pPr)
r = OxmlElement('w:r')
t = OxmlElement('w:t')
t.set(qn('xml:space'), 'preserve')
t.text = text
r.append(t)
p.append(r)
ref_element.addprevious(p)
return pdoc.add_paragraph(style='Heading 2')style.style_idstyle_name.replace(' ', '')