🌐 AI搜索 & 代理 主页
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docx/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@
from docx.parts.document import DocumentPart
from docx.parts.hdrftr import FooterPart, HeaderPart
from docx.parts.image import ImagePart
from docx.parts.altchunk import AltchunkPart
from docx.parts.numbering import NumberingPart
from docx.parts.settings import SettingsPart
from docx.parts.styles import StylesPart


def part_class_selector(content_type, reltype):
if reltype == RT.A_F_CHUNK:
return AltchunkPart
if reltype == RT.IMAGE:
return ImagePart
return None
Expand Down
51 changes: 49 additions & 2 deletions docx/oxml/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,14 @@ def OxmlElement(nsptag_str, attrs=None, nsdecls=None):
from .coreprops import CT_CoreProperties # noqa
register_element_cls('cp:coreProperties', CT_CoreProperties)

from .document import CT_Body, CT_Document # noqa
from .document import CT_Body, CT_Document, CT_altChunk # noqa
register_element_cls('w:body', CT_Body)
register_element_cls('w:document', CT_Document)
register_element_cls("w:altChunk", CT_altChunk)

from .numbering import CT_Num, CT_Numbering, CT_NumLvl, CT_NumPr # noqa
from .numbering import CT_Num, CT_Numbering, CT_NumLvl, CT_NumPr, CT_Lvl, CT_AbstractNum # noqa
register_element_cls('w:abstractNum', CT_AbstractNum)
register_element_cls('w:lvl', CT_Lvl)
register_element_cls('w:abstractNumId', CT_DecimalNumber)
register_element_cls('w:ilvl', CT_DecimalNumber)
register_element_cls('w:lvlOverride', CT_NumLvl)
Expand All @@ -85,6 +88,12 @@ def OxmlElement(nsptag_str, attrs=None, nsdecls=None):
register_element_cls('w:numPr', CT_NumPr)
register_element_cls('w:numbering', CT_Numbering)
register_element_cls('w:startOverride', CT_DecimalNumber)
register_element_cls("w:start", CT_DecimalNumber)
register_element_cls("w:numFmt", CT_String)
register_element_cls("w:lvlRestart", CT_DecimalNumber)
register_element_cls("w:suff", CT_String)
register_element_cls("w:lvlText", CT_String)
register_element_cls("w:lvlJc", CT_String)

from .section import ( # noqa
CT_HdrFtr,
Expand Down Expand Up @@ -172,6 +181,8 @@ def OxmlElement(nsptag_str, attrs=None, nsdecls=None):
register_element_cls('w:tblLayout', CT_TblLayoutType)
register_element_cls('w:tblPr', CT_TblPr)
register_element_cls('w:tblStyle', CT_String)
register_element_cls('w:tblCaption', CT_String)
register_element_cls('w:tblDescription', CT_String)
register_element_cls('w:tc', CT_Tc)
register_element_cls('w:tcPr', CT_TcPr)
register_element_cls('w:tcW', CT_TblWidth)
Expand Down Expand Up @@ -246,3 +257,39 @@ def OxmlElement(nsptag_str, attrs=None, nsdecls=None):
register_element_cls('w:br', CT_Br)
register_element_cls('w:r', CT_R)
register_element_cls('w:t', CT_Text)

from .text.form import (
CT_SimpleField,
CT_FldChar,
ST_FldCharType,
CT_FFData,
CT_FFDDList,
CT_FFCheckBox,
CT_FFTextInput,
CT_FFTextType,
)
register_element_cls('w:name', CT_String)
register_element_cls('w:label', CT_DecimalNumber)
register_element_cls('w:entryMacro', CT_String)
register_element_cls('w:exitMacro', CT_String)
register_element_cls('w:helpText', CT_String)
register_element_cls('w:StatusText', CT_String) # This is not technically correct. See 17.16.31
register_element_cls("w:checkBox", CT_FFCheckBox)
register_element_cls("w:ddList", CT_FFDDList)
register_element_cls("w:textInput", CT_FFTextInput)
register_element_cls('w:label', CT_DecimalNumber)
register_element_cls('w:fldChar', CT_FldChar)
register_element_cls('w:ffData', CT_FFData)
register_element_cls('w:instrText', CT_Text)
register_element_cls('w:default', CT_String)
register_element_cls('w:result', CT_String)
register_element_cls('w:listEntry', CT_String)
register_element_cls('w:result', CT_DecimalNumber)
register_element_cls('w:label', CT_DecimalNumber)
register_element_cls('w:checked', CT_OnOff)
register_element_cls('w:enabled', CT_OnOff)
register_element_cls('w:calcOnExit', CT_OnOff)
register_element_cls('w:maxLength', CT_DecimalNumber)
register_element_cls('w:tabIndex', CT_DecimalNumber)
register_element_cls('w:format', CT_String)
register_element_cls('w:type', CT_FFTextType)
9 changes: 8 additions & 1 deletion docx/oxml/document.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
<w:document>.
"""

from .xmlchemy import BaseOxmlElement, ZeroOrOne, ZeroOrMore
from .simpletypes import XsdString
from .xmlchemy import BaseOxmlElement, ZeroOrOne, ZeroOrMore, RequiredAttribute


class CT_Document(BaseOxmlElement):
Expand All @@ -31,6 +32,7 @@ class CT_Body(BaseOxmlElement):
p = ZeroOrMore('w:p', successors=('w:sectPr',))
tbl = ZeroOrMore('w:tbl', successors=('w:sectPr',))
sectPr = ZeroOrOne('w:sectPr', successors=())
altchunk = ZeroOrMore('w:altChunk', successors=())

def add_section_break(self):
"""Return `w:sectPr` element for new section added at end of document.
Expand Down Expand Up @@ -65,3 +67,8 @@ def clear_content(self):
content_elms = self[:]
for content_elm in content_elms:
self.remove(content_elm)


class CT_altChunk(BaseOxmlElement):
"""`w:altChunk` element"""
rId = RequiredAttribute('r:id', XsdString)
24 changes: 24 additions & 0 deletions docx/oxml/numbering.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,27 @@ def _next_numId(self):
if num not in num_ids:
break
return num


class CT_AbstractNum(BaseOxmlElement):
"""
``<w:abstractNum>`` element, which represents a concrete list definition
"""
abstractNumId = OneAndOnlyOne('w:abstractNumId')
lvl = ZeroOrOne('w:lvl')


class CT_Lvl(BaseOxmlElement):
"""
``<w:lvl>`` element, which represents a numbering level definition
"""
ilvl = RequiredAttribute("w:ilvl", ST_DecimalNumber)
start = ZeroOrOne("w:start") # register as ST_DecimalNumber
numFmt = ZeroOrOne("w:numFmt") # register as ST_String
pStyle = ZeroOrOne("w:pStyle")
lvlRestart = ZeroOrOne("w:lvlRestart") # register as ST_DecimalNumber
suff = ZeroOrOne("w:suff") # register as ST_String
lvlText = ZeroOrOne("w:lvlText") # register as ST_String
lvlJc = ZeroOrOne("w:lvlJc") # register as ST_String
pPr = ZeroOrOne("w:pPr")
rPr = ZeroOrOne("w:rPr")
120 changes: 120 additions & 0 deletions docx/oxml/text/form.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# encoding: utf-8
"""
Implementation of the following forms elements

FORMCHECKBOX (§17.16.5.20),
FORMDROPDOWN (§17.16.5.21),
FORMTEXT (§17.16.5.22)
"""

from ..simpletypes import XsdString, ST_OnOff, XsdStringEnumeration
from ..xmlchemy import (
BaseOxmlElement,
OptionalAttribute,
RequiredAttribute,
OneOrMore,
ZeroOrOne,
)


class CT_SimpleField(BaseOxmlElement):
"""
``<w:simplefield>`` element
"""

fldLock = OptionalAttribute("w:fldLock", ST_OnOff)
dirty = OptionalAttribute("w:dirty", ST_OnOff)
instr = OptionalAttribute("w:instr", XsdString)


class ST_FldCharType(XsdStringEnumeration):
"""
Valid values for <w:fldChar fldCharType=""> attribute
"""

BEGIN = "begin"
SEPARATE = "separate"
END = "end"
_members = (BEGIN, SEPARATE, END)


class CT_FldChar(BaseOxmlElement):
"""
The ``<w:fldchar">`` element
"""

ffData = ZeroOrOne("w:ffData")
fldCharType = RequiredAttribute("w:fldCharType", ST_FldCharType)
fldLock = OptionalAttribute("w:fldLock", ST_OnOff)
dirty = OptionalAttribute("w:dirty", ST_OnOff)


class CT_FFData(BaseOxmlElement):
"""
The ``<w:ffData">`` element
"""

name = ZeroOrOne("w:name")
label = ZeroOrOne("w:label")
tabIndex = ZeroOrOne("w:tabIndex")
enabled = ZeroOrOne("w:enabled")
calcOnExit = ZeroOrOne("w:calcOnExit")
entryMacro = ZeroOrOne("w:entryMacro")
exitMacro = ZeroOrOne("w:exitMacro")
helpText = ZeroOrOne("w:helpText")
statusText = ZeroOrOne("w:statusText")
checkBox = ZeroOrOne("w:checkBox")
ddList = ZeroOrOne("w:ddList")
textInput = ZeroOrOne("w:textInput")


class CT_FFDDList(BaseOxmlElement):
"""
The ``<w:ffddlist">`` element.
"""

default = ZeroOrOne("w:default")
result = ZeroOrOne("w:result")
listEntry = OneOrMore("w:listEntry")


class CT_FFCheckBox(BaseOxmlElement): # noqa
"""
The ``FFCheckBox`` element.
"""

checked = ZeroOrOne("w:checked")
default = ZeroOrOne("w:default")


class CT_FFTextInput(BaseOxmlElement): # noqa
"""
The ''<w:textinput>'' element
"""

type_ = ZeroOrOne("w:type")
default = ZeroOrOne("w:default")
format_ = ZeroOrOne("w:format")


class ST_FFTextType(XsdStringEnumeration):
"""
The ``fldCharType`` attribute of <w:fldChar> elements
"""

REGULAR = "regular"
NUMBER = "number"
DATE = "date"
CURRENTTIME = "currentTime"
CURRENTDATE = "currentDate"
CALCULATED = "calculated"
_members = (REGULAR, NUMBER, DATE, CURRENTTIME, CURRENTDATE, CALCULATED)


class CT_FFTextType(BaseOxmlElement): # noqa
"""
Used for ``<w:pStyle>`` and ``<w:tblStyle>`` elements and others,
containing a style name in its ``val`` attribute.
"""

val = RequiredAttribute("w:val", ST_FFTextType)
47 changes: 47 additions & 0 deletions docx/parts/altchunk.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# encoding: utf-8

"""The |Altchunk| and closely related objects"""

from __future__ import absolute_import, division, print_function, unicode_literals

from io import BytesIO
from docx import Document
from ..opc.part import Part

class AltchunkPart(Part):
"""AltChunkPart for word document

An AltChunk is a nested word document
"""
def __init__(self, partname, content_type, element, package):
super(AltchunkPart, self).__init__(
partname, content_type, package=package
)
self._element = element

@property
def blob(self):
stream = BytesIO()
self._element.save(stream)
return stream.getvalue()

@property
def element(self):
"""
The root XML element of this XML part.
"""
return self._element

@classmethod
def load(cls, partname, content_type, blob, package):
element = Document(BytesIO(blob))
return cls(partname, content_type, element, package)

@property
def part(self):
"""
Part of the parent protocol, "children" of the document will not know
the part that contains them so must ask their parent object. That
chain of delegation ends here for child objects.
"""
return self