Skip to content

Commit c978c05

Browse files
Benjamin-TBenjamin-T
authored andcommitted
Added support for custom xml - content control
1 parent c407dea commit c978c05

9 files changed

Lines changed: 687 additions & 34 deletions

File tree

docx/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from docx.opc.constants import CONTENT_TYPE as CT, RELATIONSHIP_TYPE as RT
1111
from docx.opc.part import PartFactory
1212
from docx.opc.parts.coreprops import CorePropertiesPart
13-
13+
from docx.opc.parts.custom_xml import CustomXmlPart
1414
from docx.parts.document import DocumentPart
1515
from docx.parts.image import ImagePart
1616
from docx.parts.numbering import NumberingPart
@@ -26,12 +26,13 @@ def part_class_selector(content_type, reltype):
2626

2727
PartFactory.part_class_selector = part_class_selector
2828
PartFactory.part_type_for[CT.OPC_CORE_PROPERTIES] = CorePropertiesPart
29+
PartFactory.part_type_for[CT.XML] = CustomXmlPart
2930
PartFactory.part_type_for[CT.WML_DOCUMENT_MAIN] = DocumentPart
3031
PartFactory.part_type_for[CT.WML_NUMBERING] = NumberingPart
3132
PartFactory.part_type_for[CT.WML_SETTINGS] = SettingsPart
3233
PartFactory.part_type_for[CT.WML_STYLES] = StylesPart
3334

3435
del (
35-
CT, CorePropertiesPart, DocumentPart, NumberingPart, PartFactory,
36+
CT, CustomXmlPart, CorePropertiesPart, DocumentPart, NumberingPart, PartFactory,
3637
StylesPart, part_class_selector
3738
)

docx/document.py

Lines changed: 6 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -403,36 +403,6 @@ def remove_picture(self, bookmark_name):
403403
p._p = None
404404
p._element = None
405405
return True
406-
# def bookmark_picture(self, bookmark_name, picture):
407-
# doc_element = self._part._element
408-
# bookmarks_list = doc_element.findall('.//' + qn('wp:docPr'))
409-
# caption_list = doc_element.findall('.//' + qn('w:fldSimple'))
410-
## print(caption_list)
411-
# for bookmark in bookmarks_list:
412-
# name = bookmark.get(qn('wp:name'))
413-
## print('bmark_id', bookmark.id)
414-
## print('bmark_name', bookmark.name)
415-
# print(bookmark.name, bookmark_name)
416-
# if bookmark.name == bookmark_name:
417-
# print(bookmark.name)
418-
# par = bookmark.getparent()
419-
# print(par)
420-
#
421-
# test = _Body(par, CT_P())
422-
# #test.clear_content()
423-
#
424-
# run = test.add_paragraph().add_run()
425-
#
426-
#
427-
# run.add_picture(picture)
428-
#
429-
## if not isinstance(par, CT_P):
430-
## return False
431-
## else:
432-
# print('Doe iets')
433-
#
434-
# return True
435-
#
436406

437407
@property
438408
def core_properties(self):
@@ -442,6 +412,12 @@ def core_properties(self):
442412
"""
443413
return self._part.core_properties
444414

415+
@property
416+
def content_control(self):
417+
"""
418+
"""
419+
return self._part.content_control
420+
445421
@property
446422
def inline_shapes(self):
447423
"""

docx/opc/customxml.py

Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
# encoding: utf-8
2+
3+
"""
4+
The :mod:`pptx.packaging` module coheres around the concerns of reading and
5+
writing presentations to and from a .pptx file.
6+
"""
7+
8+
from __future__ import (
9+
absolute_import, division, print_function, unicode_literals
10+
)
11+
12+
class CustomXmlBase(object):
13+
"""
14+
Corresponds to part named ``/CustomXml/item2.xml``, containing the core
15+
document properties for this document package.
16+
"""
17+
def __init__(self, element):
18+
self._element = element
19+
20+
class CustomXML(object):
21+
"""
22+
Corresponds to part named ``/CustomXml/item2.xml``, containing the
23+
custom content control elements for this document package.
24+
"""
25+
def __init__(self, element):
26+
self._element = element
27+
28+
@property
29+
def address(self):
30+
return self._element.address_text
31+
32+
@address.setter
33+
def address(self, value):
34+
self._element.address_text = value
35+
36+
@property
37+
def api_version(self):
38+
return self._element.apiversion_text
39+
40+
@api_version.setter
41+
def api_version(self, value):
42+
self._element.apiversion_text = value
43+
44+
@property
45+
def approved_by(self):
46+
return self._element.approvedby_text
47+
48+
@approved_by.setter
49+
def approved_by(self, value):
50+
self._element.approvedby_text = value
51+
52+
@property
53+
def authorization(self):
54+
return self._element.authorization_text
55+
56+
@authorization.setter
57+
def authorization(self, value):
58+
self._element.authorization_text = value
59+
60+
@property
61+
def checked_by(self):
62+
return self._element.checkedby_text
63+
64+
@checked_by.setter
65+
def checked_by(self, value):
66+
self._element.checkedby_text = value
67+
68+
@property
69+
def client_name(self):
70+
return self._element.clientname_text
71+
72+
@client_name.setter
73+
def client_name(self, value):
74+
self._element.clientname_text = value
75+
76+
@property
77+
def company(self):
78+
return self._element.company_text
79+
80+
@company.setter
81+
def company(self, value):
82+
self._element.company_text = value
83+
84+
@property
85+
def date(self):
86+
return self._element.date_text
87+
88+
@date.setter
89+
def date(self, value):
90+
self._element.date_text = value
91+
92+
@property
93+
def department(self):
94+
return self._element.department_text
95+
96+
@department.setter
97+
def department(self, value):
98+
self._element.department_text = value
99+
100+
@property
101+
def document_number(self):
102+
return self._element.documentnumber_text
103+
104+
@document_number.setter
105+
def document_number(self, value):
106+
self._element.documentnumber_text = value
107+
108+
@property
109+
def document_type(self):
110+
return self._element.documenttype_text
111+
112+
@document_type.setter
113+
def document_type(self, value):
114+
self._element.documenttype_text = value
115+
116+
@property
117+
def email(self):
118+
return self._element.email_text
119+
120+
@email.setter
121+
def email(self, value):
122+
self._element.email_text = value
123+
124+
@property
125+
def function(self):
126+
return self._element.function_text
127+
128+
@function.setter
129+
def function(self, value):
130+
self._element.function_text = value
131+
132+
@property
133+
def function_excerpt(self):
134+
return self._element.functionexcerpt_text
135+
136+
@function_excerpt.setter
137+
def function_excerpt(self, value):
138+
self._element.functionexcerpt_text = value
139+
140+
@property
141+
def location(self):
142+
return self._element.location_text
143+
144+
@location.setter
145+
def location(self, value):
146+
self._element.location_text = value
147+
148+
@property
149+
def name(self):
150+
return self._element.name_text
151+
152+
@name.setter
153+
def name(self, value):
154+
self._element.name_text = value
155+
156+
@property
157+
def prepared_by(self):
158+
return self._element.preparedby_text
159+
160+
@prepared_by.setter
161+
def prepared_by(self, value):
162+
self._element.preparedby_text = value
163+
164+
@property
165+
def project_director(self):
166+
return self._element.projectdirector_text
167+
168+
@project_director.setter
169+
def project_director(self, value):
170+
self._element.projectdirector_text = value
171+
172+
@property
173+
def project_name(self):
174+
return self._element.projectname_text
175+
176+
@project_name.setter
177+
def project_name(self, value):
178+
self._element.projectname_text = value
179+
180+
@property
181+
def project_title(self):
182+
return self._element.projecttitle_text
183+
184+
@project_title.setter
185+
def project_title(self, value):
186+
self._element.projecttitle_text = value
187+
188+
@property
189+
def project_code(self):
190+
return self._element.projectcode_text
191+
192+
@project_code.setter
193+
def project_code(self, value):
194+
self._element.projectcode_text = value
195+
196+
@property
197+
def recipient(self):
198+
return self._element.recipient_text
199+
200+
@recipient.setter
201+
def recipient(self, value):
202+
self._element.recipient_text = value
203+
204+
@property
205+
def reference(self):
206+
return self._element.reference_text
207+
208+
@reference.setter
209+
def reference(self, value):
210+
self._element.reference_text = value
211+
212+
@property
213+
def report_date(self):
214+
return self._element.reportdate_text
215+
216+
@report_date.setter
217+
def report_date(self, value):
218+
self._element.reportdate_text = value
219+
220+
@property
221+
def report_number(self):
222+
return self._element.reportnumber_text
223+
224+
@report_number.setter
225+
def report_number(self, value):
226+
self._element.reportnumber_text = value
227+
228+
@property
229+
def revision(self):
230+
return self._element.revision_text
231+
232+
@revision.setter
233+
def revision(self, value):
234+
self._element.revision_text = value
235+
236+
@property
237+
def surname(self):
238+
return self._element.surname_text
239+
240+
@surname.setter
241+
def surname(self, value):
242+
self._element.surname_text = value
243+
244+
@property
245+
def telephone(self):
246+
return self._element.telephone_text
247+
248+
@telephone.setter
249+
def telephone(self, value):
250+
self._element.telephone_text = value
251+
252+
@property
253+
def your_reference(self):
254+
return self._element.yourreference_text
255+
256+
@your_reference.setter
257+
def your_reference(self, value):
258+
self._element.yourreference_text = value

docx/opc/part.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,17 @@ def drop_rel(self, rId):
7373
"""
7474
if self._rel_ref_count(rId) < 2:
7575
del self.rels[rId]
76-
76+
77+
def iter_parts_related_by(self, reltypes):
78+
"""Generate each part related to this by one of *reltypes*.
79+
*reltypes* must be a container; `set` is convenient but list or other
80+
sequence types work fine.
81+
"""
82+
return (
83+
rel.target_part for rel in self.rels.values()
84+
if rel.reltype in reltypes
85+
)
86+
7787
@classmethod
7888
def load(cls, partname, content_type, blob, package):
7989
return cls(partname, content_type, blob, package)

docx/opc/parts/custom_xml.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# encoding: utf-8
2+
3+
"""
4+
Core properties part, corresponds to ``/docProps/core.xml`` part in package.
5+
"""
6+
7+
from __future__ import (
8+
absolute_import, division, print_function, unicode_literals
9+
)
10+
11+
from datetime import datetime
12+
13+
from ..constants import CONTENT_TYPE as CT
14+
from ..customxml import CustomXML, CustomXmlBase
15+
from ...oxml.customxml import CT_CustomXML
16+
from ..packuri import PackURI
17+
from ..part import XmlPart
18+
19+
20+
class CustomXmlPart(XmlPart):
21+
"""
22+
23+
"""
24+
@property
25+
def custom_xml(self):
26+
"""
27+
A |CoreProperties| object providing read/write access to the core
28+
properties contained in this core properties part.
29+
"""
30+
if type(self._element) == CT_CustomXML:
31+
return CustomXML(self.element)
32+
else:
33+
return CustomXmlBase(self.element)
34+
35+
@classmethod
36+
def _new(cls, package):
37+
partname = PackURI('/customXml/item2.xml')
38+
content_type = CT.XML
39+
custom_Xml = CT_CustomXML.new()
40+
return CustomXmlPart(
41+
partname, content_type, custom_Xml, package
42+
)

0 commit comments

Comments
 (0)