docx/list-numbering-format--decimal-enclosed-circle-chinese

Exercise ST_NumberFormat values (decimal, upperRoman, ideographDigital, aiueo, ...) on a single-level numbered list via <w:lvl>/<w:numFmt>.

Library verdicts: python-docx: — docxjs: —

Metadata

Feature iddocx/list-numbering-format--decimal-enclosed-circle-chinese
Formatdocx
Categorylists
Familydocx/list-numbering-format
Axis valuesnumfmt=decimal-enclosed-circle-chinese
Spececma-376-5-part-1 § 17.9.17 w:numFmt

XPath assertions

ID / partPredicateXPathpython-docxdocxjs
list-numbering-format-decimal-enclosed-circle-chinese-numfmt-present
word/numbering.xml
exist
The numbering part must contain a <w:lvl>/<w:numFmt> whose @w:val is 'decimalEnclosedCircleChinese'.
//w:lvl/w:numFmt[@w:val='decimalEnclosedCircleChinese']

Render assertions

No render assertions declared.

Generator source

scripts/gen_list_numbering_format.py

#!/usr/bin/env python3
"""Generate a ``fixtures/docx/list-numbering-format--<id>.docx`` fixture.

Parameterised family exercising ST_NumberFormat values (ECMA-376 Part 1
clause 17.9.17). Each generated fixture contains a single numbered list
item (``numId=1``, ``ilvl=0``) whose abstract-num level declares the
specified ``w:numFmt/@w:val``.

python-docx's high-level numbering API does not expose per-level
``w:numFmt`` control, so the numbering part is built from scratch via
``OxmlElement`` (bypassing the :class:`WD_NUMBER_FORMAT` enum, which
only covers the most common subset).
"""

from __future__ import annotations

import argparse
from pathlib import Path

from docx import Document
from docx.oxml import OxmlElement
from docx.oxml.ns import qn

_REPO_ROOT = Path(__file__).resolve().parent.parent


def _write(numfmt_val: str, out: Path) -> None:
    doc = Document()

    # Ensure numbering part exists, then wipe any existing abstractNum / num
    # so the fixture starts from a clean slate.
    numbering = doc.part.numbering_part.element
    for child in list(numbering):
        if child.tag in (qn("w:num"), qn("w:abstractNum")):
            numbering.remove(child)

    abs_num = OxmlElement("w:abstractNum")
    abs_num.set(qn("w:abstractNumId"), "0")

    lvl = OxmlElement("w:lvl")
    lvl.set(qn("w:ilvl"), "0")

    start = OxmlElement("w:start")
    start.set(qn("w:val"), "1")
    lvl.append(start)

    fmt = OxmlElement("w:numFmt")
    fmt.set(qn("w:val"), numfmt_val)
    lvl.append(fmt)

    lvl_text = OxmlElement("w:lvlText")
    lvl_text.set(qn("w:val"), "%1.")
    lvl.append(lvl_text)

    abs_num.append(lvl)
    numbering.append(abs_num)

    num = OxmlElement("w:num")
    num.set(qn("w:numId"), "1")
    abs_ref = OxmlElement("w:abstractNumId")
    abs_ref.set(qn("w:val"), "0")
    num.append(abs_ref)
    numbering.append(num)

    p = doc.add_paragraph("Numbered item one")
    pPr = p._p.get_or_add_pPr()
    numPr = OxmlElement("w:numPr")
    ilvl = OxmlElement("w:ilvl")
    ilvl.set(qn("w:val"), "0")
    numPr.append(ilvl)
    numId = OxmlElement("w:numId")
    numId.set(qn("w:val"), "1")
    numPr.append(numId)
    pPr.append(numPr)

    out.parent.mkdir(parents=True, exist_ok=True)
    doc.save(out, reproducible=True)


def main() -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument("--numfmt", required=True, help="ST_NumberFormat value, e.g. 'decimal'")
    parser.add_argument("--out", required=True)
    args = parser.parse_args()

    out_path = Path(args.out)
    if not out_path.is_absolute():
        out_path = _REPO_ROOT / out_path
    _write(args.numfmt, out_path)
    print(out_path)
    return 0


if __name__ == "__main__":
    raise SystemExit(main())

Manifest (expanded)

{
  "$schema": "../manifest.schema.json",
  "id": "docx/list-numbering-format--decimal-enclosed-circle-chinese",
  "kind": "literal",
  "title": "List numbering format",
  "format": "docx",
  "category": "lists",
  "summary": "Exercise ST_NumberFormat values (decimal, upperRoman, ideographDigital, aiueo, ...) on a single-level numbered list via <w:lvl>/<w:numFmt>.",
  "spec": {
    "source": "ecma-376-5-part-1",
    "clause": "17.9.17",
    "element": "w:numFmt",
    "rnc_reference": "spec/ecma-376-5/part-1/rnc/WordprocessingML.rnc",
    "xsd_reference": "spec/ecma-376-5/part-1/xsd/wml.xsd",
    "notes": "ST_NumberFormat is the simple type backing <w:numFmt w:val='...'/>. It enumerates ~60 numbering-style tokens (decimal, upperRoman, ordinal, cardinalText, chicago, ideographDigital, japaneseCounting, aiueo, iroha, decimalFullWidth, ganada, chosung, decimalEnclosedCircle, bullet, ...). Each parameter case in this family emits a fresh numbering part containing one <w:abstractNum> with a single <w:lvl ilvl='0'> whose <w:numFmt/@w:val> is the parameter token, plus one <w:num numId='1'> that references it. A paragraph in word/document.xml carries <w:numPr><w:numId val='1'/></w:numPr> to pull the item into that list. python-docx's WD_NUMBER_FORMAT enum only covers the common subset; the generator builds the numFmt via OxmlElement to bypass that restriction."
  },
  "fixtures": {
    "machine": "docx/list-numbering-format--decimal-enclosed-circle-chinese"
  },
  "generator": {
    "python": "scripts/gen_list_numbering_format.py",
    "arg_template": "--numfmt {numfmt.val} --out fixtures/docx/list-numbering-format--{numfmt.id}.docx"
  },
  "_expansion": {
    "parent_id": "docx/list-numbering-format",
    "bindings": {
      "numfmt": "decimal-enclosed-circle-chinese"
    }
  },
  "assertions": [
    {
      "id": "list-numbering-format-decimal-enclosed-circle-chinese-numfmt-present",
      "part": "word/numbering.xml",
      "namespaces": {
        "w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
      },
      "xpath": "//w:lvl/w:numFmt[@w:val='decimalEnclosedCircleChinese']",
      "must": "exist",
      "description": "The numbering part must contain a <w:lvl>/<w:numFmt> whose @w:val is 'decimalEnclosedCircleChinese'."
    }
  ]
}

Fixture

Download list-numbering-format--decimal-enclosed-circle-chinese.docx (19.2 KB)

Reference preview

Reference (machine, page 1 PNG)

docx/list-numbering-format--decimal-enclosed-circle-chinese page 1 reference

Reference PDF


Download PDF Open in PDF.js

Spec notes

ST_NumberFormat is the simple type backing <w:numFmt w:val='...'/>. It enumerates ~60 numbering-style tokens (decimal, upperRoman, ordinal, cardinalText, chicago, ideographDigital, japaneseCounting, aiueo, iroha, decimalFullWidth, ganada, chosung, decimalEnclosedCircle, bullet, ...). Each parameter case in this family emits a fresh numbering part containing one <w:abstractNum> with a single <w:lvl ilvl='0'> whose <w:numFmt/@w:val> is the parameter token, plus one <w:num numId='1'> that references it. A paragraph in word/document.xml carries <w:numPr><w:numId val='1'/></w:numPr> to pull the item into that list. python-docx's WD_NUMBER_FORMAT enum only covers the common subset; the generator builds the numFmt via OxmlElement to bypass that restriction.