diff --git a/docx/__init__.py b/docx/__init__.py index 1bba46ad5..8489f8730 100644 --- a/docx/__init__.py +++ b/docx/__init__.py @@ -14,6 +14,7 @@ from docx.parts.image import ImagePart from docx.parts.numbering import NumberingPart from docx.parts.styles import StylesPart +from docx.parts.header import HeaderPart def part_class_selector(content_type, reltype): @@ -26,5 +27,6 @@ def part_class_selector(content_type, reltype): PartFactory.part_type_for[CT.WML_DOCUMENT_MAIN] = DocumentPart PartFactory.part_type_for[CT.WML_NUMBERING] = NumberingPart PartFactory.part_type_for[CT.WML_STYLES] = StylesPart +PartFactory.part_type_for[CT.WML_HEADER] = HeaderPart del CT, DocumentPart, PartFactory, part_class_selector diff --git a/docx/api.py b/docx/api.py index 7d268af8b..2183e9569 100644 --- a/docx/api.py +++ b/docx/api.py @@ -16,6 +16,7 @@ from docx.package import Package from docx.parts.numbering import NumberingPart from docx.parts.styles import StylesPart +from docx.parts.header import HeaderPart from docx.shared import lazyproperty @@ -177,6 +178,22 @@ def styles_part(self): self._document_part.relate_to(styles_part, RT.STYLES) return styles_part + @lazyproperty + def header_part(self, section=None): + """ + Instance of |HeaderPart| for this document. Takes a section argument. + If none is passed, assumes default (sentinel) Section. + Creates an empty header part if one is not present. + """ + if not section: + section = self.sections()[0] + try: + return self._document_part.part_related_by(RT.HEADER) + except KeyError: + header_part = HeaderPart.new() + self._document_part.relate_to(header_part, RT.HEADER) + return header_part + @property def tables(self): """ diff --git a/docx/oxml/parts/__init__.py b/docx/oxml/parts/__init__.py index e69de29bb..40a96afc6 100644 --- a/docx/oxml/parts/__init__.py +++ b/docx/oxml/parts/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/docx/oxml/parts/header.py b/docx/oxml/parts/header.py new file mode 100644 index 000000000..658143405 --- /dev/null +++ b/docx/oxml/parts/header.py @@ -0,0 +1,50 @@ +# encoding: utf-8 + +""" +Custom element classes related to the header part +""" + +from docx.oxml.shared import nsmap, OxmlBaseElement, qn + + +class CT_Header(OxmlBaseElement): + """ + A ```` element, representing a header definition + """ + @property + def pPr(self): + return self.find(qn('w:pPr')) + + + def header_having_headerId(self, headerId): + """ + Return the ```` child element having ``headerId`` attribute + matching *headerId*. + """ + xpath = './w:hdr[@w:hdrId="%s"]' % headerId + try: + return self.xpath(xpath, namespaces=nsmap)[0] + except IndexError: + raise KeyError('no element with hdrId %d' % headerId) + + @property + def header_lst(self): + """ + List of child elements. + """ + return self.findall(qn('w:hdr')) + + @classmethod + def new(cls, hdr_id, abstractHdr_id): + """ + Return a new ```` element having numId of *num_id* and having + a ```` child with val attribute set to + *abstractNum_id*. + """ + header = OxmlElement('w:hdr') + header.hdrId = hdr_id + abstractHdrId = CT_DecimalNumber.new( + 'w:abstractHdrId', abstractHdr_id + ) + nhdr.append(abstractHdrId) + return header \ No newline at end of file diff --git a/docx/parts/header.py b/docx/parts/header.py new file mode 100644 index 000000000..82844e4fc --- /dev/null +++ b/docx/parts/header.py @@ -0,0 +1,64 @@ +# encoding: utf-8 + +""" +Provides HeaderPart and related objects +""" + +from __future__ import ( + absolute_import, division, print_function, unicode_literals +) + +from ..opc.package import Part +from ..oxml.shared import oxml_fromstring +from ..shared import lazyproperty + + +class HeaderPart(Part): + """ + Proxy for the styles.xml part containing style definitions for a document + or glossary. + """ + def __init__(self, partname, content_type, element, package): + super(HeaderPart, self).__init__( + partname, content_type, element=element, package=package + ) + + @classmethod + def load(cls, partname, content_type, blob, package): + """ + Provides PartFactory interface for loading a styles part from a WML + package. + """ + styles_elm = oxml_fromstring(blob) + styles_part = cls(partname, content_type, styles_elm, package) + return styles_part + + @classmethod + def new(cls): + """ + Return newly created empty header part, containing only the root + ```` element. + """ + # call oxml class method CT_Header.new() + raise NotImplementedError + + @lazyproperty + def header(self): + """ + The |_Header| instance containing the header ( element + proxies) for this header part. + """ + return _Header(self._element) + + +class _Header(object): + """ + FIX THIS >>> Collection of |_Header| instances corresponding to the ```` + elements in a header part. + """ + def __init__(self, header_elm): + super(_Header, self).__init__() + self._header_elm = header_elm + + def __len__(self): + return len(self._styles_elm.header_lst) \ No newline at end of file