Replaxe lxml with standard library xml in ODT class

This commit is contained in:
Veronica Berglyd Olsen
2023-05-29 20:04:28 +02:00
parent 47a6ae5031
commit 22e0f82654
+113 -122
View File
@@ -24,13 +24,14 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
""" """
import logging import logging
import xml.etree.ElementTree as ET
from lxml import etree
from hashlib import sha256 from hashlib import sha256
from zipfile import ZipFile from zipfile import ZipFile
from datetime import datetime from datetime import datetime
from novelwriter import __version__ from novelwriter import __version__
from novelwriter.common import xmlIndent
from novelwriter.constants import nwKeyWords, nwLabels from novelwriter.constants import nwKeyWords, nwLabels
from novelwriter.core.tokenizer import Tokenizer, stripEscape from novelwriter.core.tokenizer import Tokenizer, stripEscape
@@ -38,30 +39,27 @@ logger = logging.getLogger(__name__)
# Main XML NameSpaces # Main XML NameSpaces
XML_NS = { XML_NS = {
"office": "urn:oasis:names:tc:opendocument:xmlns:office:1.0", "manifest": "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0",
"style": "urn:oasis:names:tc:opendocument:xmlns:style:1.0", "office": "urn:oasis:names:tc:opendocument:xmlns:office:1.0",
"loext": "urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0", "style": "urn:oasis:names:tc:opendocument:xmlns:style:1.0",
"text": "urn:oasis:names:tc:opendocument:xmlns:text:1.0", "loext": "urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0",
"meta": "urn:oasis:names:tc:opendocument:xmlns:meta:1.0", "text": "urn:oasis:names:tc:opendocument:xmlns:text:1.0",
"fo": "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0", "meta": "urn:oasis:names:tc:opendocument:xmlns:meta:1.0",
"dc": "http://purl.org/dc/elements/1.1/", "fo": "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0",
} "dc": "http://purl.org/dc/elements/1.1/",
MANI_NS = {
"manifest": "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"
}
OFFICE_NS = {
"office": "urn:oasis:names:tc:opendocument:xmlns:office:1.0",
} }
for ns, uri in XML_NS.items():
ET.register_namespace(ns, uri)
def _mkTag(nsName, tagName, nsMap=XML_NS): def _mkTag(ns, tag):
"""Assemble namespace and tag name. """Assemble namespace and tag name.
""" """
theNS = nsMap.get(nsName, "") uri = XML_NS.get(ns, "")
if theNS: if uri:
return f"{{{theNS}}}{tagName}" return f"{{{uri}}}{tag}"
logger.warning("Missing xml namespace '%s'", nsName) logger.warning("Missing xml namespace '%s'", ns)
return tagName return tag
# Mimetype and Version # Mimetype and Version
@@ -284,16 +282,16 @@ class ToOdt(Tokenizer):
tAttr[_mkTag("office", "mimetype")] = X_MIME tAttr[_mkTag("office", "mimetype")] = X_MIME
tFlat = _mkTag("office", "document") tFlat = _mkTag("office", "document")
self._dFlat = etree.Element(tFlat, attrib=tAttr, nsmap=XML_NS) self._dFlat = ET.Element(tFlat, attrib=tAttr)
self._xMeta = etree.SubElement(self._dFlat, _mkTag("office", "meta")) self._xMeta = ET.SubElement(self._dFlat, _mkTag("office", "meta"))
self._xFont = etree.SubElement(self._dFlat, _mkTag("office", "font-face-decls")) self._xFont = ET.SubElement(self._dFlat, _mkTag("office", "font-face-decls"))
self._xStyl = etree.SubElement(self._dFlat, _mkTag("office", "styles")) self._xStyl = ET.SubElement(self._dFlat, _mkTag("office", "styles"))
self._xAuto = etree.SubElement(self._dFlat, _mkTag("office", "automatic-styles")) self._xAuto = ET.SubElement(self._dFlat, _mkTag("office", "automatic-styles"))
self._xMast = etree.SubElement(self._dFlat, _mkTag("office", "master-styles")) self._xMast = ET.SubElement(self._dFlat, _mkTag("office", "master-styles"))
self._xBody = etree.SubElement(self._dFlat, _mkTag("office", "body")) self._xBody = ET.SubElement(self._dFlat, _mkTag("office", "body"))
etree.SubElement(self._xFont, _mkTag("style", "font-face"), attrib=fAttr) ET.SubElement(self._xFont, _mkTag("style", "font-face"), attrib=fAttr)
else: else:
@@ -305,59 +303,59 @@ class ToOdt(Tokenizer):
tStyl = _mkTag("office", "document-styles") tStyl = _mkTag("office", "document-styles")
# content.xml # content.xml
self._dCont = etree.Element(tCont, attrib=tAttr, nsmap=XML_NS) self._dCont = ET.Element(tCont, attrib=tAttr)
self._xFont = etree.SubElement(self._dCont, _mkTag("office", "font-face-decls")) self._xFont = ET.SubElement(self._dCont, _mkTag("office", "font-face-decls"))
self._xAuto = etree.SubElement(self._dCont, _mkTag("office", "automatic-styles")) self._xAuto = ET.SubElement(self._dCont, _mkTag("office", "automatic-styles"))
self._xBody = etree.SubElement(self._dCont, _mkTag("office", "body")) self._xBody = ET.SubElement(self._dCont, _mkTag("office", "body"))
# meta.xml # meta.xml
self._dMeta = etree.Element(tMeta, attrib=tAttr, nsmap=XML_NS) self._dMeta = ET.Element(tMeta, attrib=tAttr)
self._xMeta = etree.SubElement(self._dMeta, _mkTag("office", "meta")) self._xMeta = ET.SubElement(self._dMeta, _mkTag("office", "meta"))
# styles.xml # styles.xml
self._dStyl = etree.Element(tStyl, attrib=tAttr, nsmap=XML_NS) self._dStyl = ET.Element(tStyl, attrib=tAttr)
self._xFnt2 = etree.SubElement(self._dStyl, _mkTag("office", "font-face-decls")) self._xFnt2 = ET.SubElement(self._dStyl, _mkTag("office", "font-face-decls"))
self._xStyl = etree.SubElement(self._dStyl, _mkTag("office", "styles")) self._xStyl = ET.SubElement(self._dStyl, _mkTag("office", "styles"))
self._xAut2 = etree.SubElement(self._dStyl, _mkTag("office", "automatic-styles")) self._xAut2 = ET.SubElement(self._dStyl, _mkTag("office", "automatic-styles"))
self._xMast = etree.SubElement(self._dStyl, _mkTag("office", "master-styles")) self._xMast = ET.SubElement(self._dStyl, _mkTag("office", "master-styles"))
etree.SubElement(self._xFont, _mkTag("style", "font-face"), attrib=fAttr) ET.SubElement(self._xFont, _mkTag("style", "font-face"), attrib=fAttr)
etree.SubElement(self._xFnt2, _mkTag("style", "font-face"), attrib=fAttr) ET.SubElement(self._xFnt2, _mkTag("style", "font-face"), attrib=fAttr)
# Finalise # Finalise
# ======== # ========
self._xText = etree.SubElement(self._xBody, _mkTag("office", "text")) self._xText = ET.SubElement(self._xBody, _mkTag("office", "text"))
timeStamp = datetime.now().isoformat(sep="T", timespec="seconds") timeStamp = datetime.now().isoformat(sep="T", timespec="seconds")
# Office Meta Data # Office Meta Data
xMeta = etree.SubElement(self._xMeta, _mkTag("meta", "creation-date")) xMeta = ET.SubElement(self._xMeta, _mkTag("meta", "creation-date"))
xMeta.text = timeStamp xMeta.text = timeStamp
xMeta = etree.SubElement(self._xMeta, _mkTag("meta", "generator")) xMeta = ET.SubElement(self._xMeta, _mkTag("meta", "generator"))
xMeta.text = f"novelWriter/{__version__}" xMeta.text = f"novelWriter/{__version__}"
xMeta = etree.SubElement(self._xMeta, _mkTag("meta", "initial-creator")) xMeta = ET.SubElement(self._xMeta, _mkTag("meta", "initial-creator"))
xMeta.text = self.theProject.data.author xMeta.text = self.theProject.data.author
xMeta = etree.SubElement(self._xMeta, _mkTag("meta", "editing-cycles")) xMeta = ET.SubElement(self._xMeta, _mkTag("meta", "editing-cycles"))
xMeta.text = str(self.theProject.data.saveCount) xMeta.text = str(self.theProject.data.saveCount)
# Format is: PnYnMnDTnHnMnS # Format is: PnYnMnDTnHnMnS
# https://www.w3.org/TR/2004/REC-xmlschema-2-20041028/#duration # https://www.w3.org/TR/2004/REC-xmlschema-2-20041028/#duration
eT = self.theProject.data.editTime eT = self.theProject.data.editTime
xMeta = etree.SubElement(self._xMeta, _mkTag("meta", "editing-duration")) xMeta = ET.SubElement(self._xMeta, _mkTag("meta", "editing-duration"))
xMeta.text = f"P{eT//86400:d}DT{eT%86400//3600:d}H{eT%3600//60:d}M{eT%60:d}S" xMeta.text = f"P{eT//86400:d}DT{eT%86400//3600:d}H{eT%3600//60:d}M{eT%60:d}S"
# Dublin Core Meta Data # Dublin Core Meta Data
xMeta = etree.SubElement(self._xMeta, _mkTag("dc", "title")) xMeta = ET.SubElement(self._xMeta, _mkTag("dc", "title"))
xMeta.text = self.theProject.data.title or self.theProject.data.name xMeta.text = self.theProject.data.title or self.theProject.data.name
xMeta = etree.SubElement(self._xMeta, _mkTag("dc", "date")) xMeta = ET.SubElement(self._xMeta, _mkTag("dc", "date"))
xMeta.text = timeStamp xMeta.text = timeStamp
xMeta = etree.SubElement(self._xMeta, _mkTag("dc", "creator")) xMeta = ET.SubElement(self._xMeta, _mkTag("dc", "creator"))
xMeta.text = self.theProject.data.author xMeta.text = self.theProject.data.author
self._pageStyles() self._pageStyles()
@@ -503,51 +501,44 @@ class ToOdt(Tokenizer):
"""Save the data to an .fodt file. """Save the data to an .fodt file.
""" """
with open(savePath, mode="wb") as outFile: with open(savePath, mode="wb") as outFile:
outFile.write(etree.tostring( xml = ET.ElementTree(self._dFlat)
self._dFlat, xmlIndent(xml, space=" ")
pretty_print=True, xml.write(outFile, encoding="utf-8", xml_declaration=True)
encoding="utf-8",
xml_declaration=True
))
return return
def saveOpenDocText(self, savePath): def saveOpenDocText(self, savePath):
"""Save the data to an .odt file. """Save the data to an .odt file.
""" """
mMani = _mkTag("manifest", "manifest", nsMap=MANI_NS) mMani = _mkTag("manifest", "manifest")
mVers = _mkTag("manifest", "version", nsMap=MANI_NS) mVers = _mkTag("manifest", "version")
mPath = _mkTag("manifest", "full-path", nsMap=MANI_NS) mPath = _mkTag("manifest", "full-path")
mType = _mkTag("manifest", "media-type", nsMap=MANI_NS) mType = _mkTag("manifest", "media-type")
mFile = _mkTag("manifest", "file-entry", nsMap=MANI_NS) mFile = _mkTag("manifest", "file-entry")
xMani = etree.Element(mMani, attrib={mVers: X_VERS}, nsmap=MANI_NS) xMani = ET.Element(mMani, attrib={mVers: X_VERS})
etree.SubElement(xMani, mFile, attrib={mPath: "/", mVers: X_VERS, mType: X_MIME}) ET.SubElement(xMani, mFile, attrib={mPath: "/", mVers: X_VERS, mType: X_MIME})
etree.SubElement(xMani, mFile, attrib={mPath: "settings.xml", mType: "text/xml"}) ET.SubElement(xMani, mFile, attrib={mPath: "settings.xml", mType: "text/xml"})
etree.SubElement(xMani, mFile, attrib={mPath: "content.xml", mType: "text/xml"}) ET.SubElement(xMani, mFile, attrib={mPath: "content.xml", mType: "text/xml"})
etree.SubElement(xMani, mFile, attrib={mPath: "meta.xml", mType: "text/xml"}) ET.SubElement(xMani, mFile, attrib={mPath: "meta.xml", mType: "text/xml"})
etree.SubElement(xMani, mFile, attrib={mPath: "styles.xml", mType: "text/xml"}) ET.SubElement(xMani, mFile, attrib={mPath: "styles.xml", mType: "text/xml"})
oRoot = _mkTag("office", "document-settings", nsMap=OFFICE_NS) oRoot = _mkTag("office", "document-settings")
oVers = _mkTag("office", "version", nsMap=OFFICE_NS) oVers = _mkTag("office", "version")
xSett = etree.Element(oRoot, nsmap=OFFICE_NS, attrib={oVers: X_VERS}) xSett = ET.Element(oRoot, attrib={oVers: X_VERS})
with ZipFile(savePath, mode="w") as outFile: def putInZip(name, xObj, zipObj):
outFile.writestr("mimetype", X_MIME) with zipObj.open(name, mode="w") as fObj:
outFile.writestr("META-INF/manifest.xml", etree.tostring( xml = ET.ElementTree(xObj)
xMani, pretty_print=False, encoding="utf-8", xml_declaration=True xmlIndent(xml, space=" ")
)) xml.write(fObj, encoding="utf-8", xml_declaration=True)
outFile.writestr("settings.xml", etree.tostring(
xSett, pretty_print=False, encoding="utf-8", xml_declaration=True with ZipFile(savePath, mode="w") as outZip:
)) outZip.writestr("mimetype", X_MIME)
outFile.writestr("content.xml", etree.tostring( putInZip("META-INF/manifest.xml", xMani, outZip)
self._dCont, pretty_print=False, encoding="utf-8", xml_declaration=True putInZip("settings.xml", xSett, outZip)
)) putInZip("content.xml", self._dCont, outZip)
outFile.writestr("meta.xml", etree.tostring( putInZip("meta.xml", self._dMeta, outZip)
self._dMeta, pretty_print=False, encoding="utf-8", xml_declaration=True putInZip("styles.xml", self._dStyl, outZip)
))
outFile.writestr("styles.xml", etree.tostring(
self._dStyl, pretty_print=False, encoding="utf-8", xml_declaration=True
))
return return
@@ -604,7 +595,7 @@ class ToOdt(Tokenizer):
tAttr[_mkTag("text", "outline-level")] = oLevel tAttr[_mkTag("text", "outline-level")] = oLevel
pTag = "h" if isHead else "p" pTag = "h" if isHead else "p"
xElem = etree.SubElement(self._xText, _mkTag("text", pTag), attrib=tAttr) xElem = ET.SubElement(self._xText, _mkTag("text", pTag), attrib=tAttr)
# It's important to set the initial text field to empty, otherwise # It's important to set the initial text field to empty, otherwise
# lxml will add a line break if the first subelement is a span. # lxml will add a line break if the first subelement is a span.
@@ -732,25 +723,25 @@ class ToOdt(Tokenizer):
theAttr = {} theAttr = {}
theAttr[_mkTag("style", "name")] = "PM1" theAttr[_mkTag("style", "name")] = "PM1"
if self._isFlat: if self._isFlat:
xPage = etree.SubElement(self._xAuto, _mkTag("style", "page-layout"), attrib=theAttr) xPage = ET.SubElement(self._xAuto, _mkTag("style", "page-layout"), attrib=theAttr)
else: else:
xPage = etree.SubElement(self._xAut2, _mkTag("style", "page-layout"), attrib=theAttr) xPage = ET.SubElement(self._xAut2, _mkTag("style", "page-layout"), attrib=theAttr)
theAttr = {} theAttr = {}
theAttr[_mkTag("fo", "margin-top")] = self._mDocTop theAttr[_mkTag("fo", "margin-top")] = self._mDocTop
theAttr[_mkTag("fo", "margin-bottom")] = self._mDocBtm theAttr[_mkTag("fo", "margin-bottom")] = self._mDocBtm
theAttr[_mkTag("fo", "margin-left")] = self._mDocLeft theAttr[_mkTag("fo", "margin-left")] = self._mDocLeft
theAttr[_mkTag("fo", "margin-right")] = self._mDocRight theAttr[_mkTag("fo", "margin-right")] = self._mDocRight
etree.SubElement(xPage, _mkTag("style", "page-layout-properties"), attrib=theAttr) ET.SubElement(xPage, _mkTag("style", "page-layout-properties"), attrib=theAttr)
xHead = etree.SubElement(xPage, _mkTag("style", "header-style")) xHead = ET.SubElement(xPage, _mkTag("style", "header-style"))
theAttr = {} theAttr = {}
theAttr[_mkTag("fo", "min-height")] = "0.600cm" theAttr[_mkTag("fo", "min-height")] = "0.600cm"
theAttr[_mkTag("fo", "margin-left")] = "0.000cm" theAttr[_mkTag("fo", "margin-left")] = "0.000cm"
theAttr[_mkTag("fo", "margin-right")] = "0.000cm" theAttr[_mkTag("fo", "margin-right")] = "0.000cm"
theAttr[_mkTag("fo", "margin-bottom")] = "0.500cm" theAttr[_mkTag("fo", "margin-bottom")] = "0.500cm"
etree.SubElement(xHead, _mkTag("style", "header-footer-properties"), attrib=theAttr) ET.SubElement(xHead, _mkTag("style", "header-footer-properties"), attrib=theAttr)
return return
@@ -762,13 +753,13 @@ class ToOdt(Tokenizer):
theAttr = {} theAttr = {}
theAttr[_mkTag("style", "family")] = "paragraph" theAttr[_mkTag("style", "family")] = "paragraph"
xStyl = etree.SubElement(self._xStyl, _mkTag("style", "default-style"), attrib=theAttr) xStyl = ET.SubElement(self._xStyl, _mkTag("style", "default-style"), attrib=theAttr)
theAttr = {} theAttr = {}
theAttr[_mkTag("style", "line-break")] = "strict" theAttr[_mkTag("style", "line-break")] = "strict"
theAttr[_mkTag("style", "tab-stop-distance")] = "1.251cm" theAttr[_mkTag("style", "tab-stop-distance")] = "1.251cm"
theAttr[_mkTag("style", "writing-mode")] = "page" theAttr[_mkTag("style", "writing-mode")] = "page"
etree.SubElement(xStyl, _mkTag("style", "paragraph-properties"), attrib=theAttr) ET.SubElement(xStyl, _mkTag("style", "paragraph-properties"), attrib=theAttr)
theAttr = {} theAttr = {}
theAttr[_mkTag("style", "font-name")] = self._textFont theAttr[_mkTag("style", "font-name")] = self._textFont
@@ -776,7 +767,7 @@ class ToOdt(Tokenizer):
theAttr[_mkTag("fo", "font-size")] = self._fSizeText theAttr[_mkTag("fo", "font-size")] = self._fSizeText
theAttr[_mkTag("fo", "language")] = self._dLanguage theAttr[_mkTag("fo", "language")] = self._dLanguage
theAttr[_mkTag("fo", "country")] = self._dCountry theAttr[_mkTag("fo", "country")] = self._dCountry
etree.SubElement(xStyl, _mkTag("style", "text-properties"), attrib=theAttr) ET.SubElement(xStyl, _mkTag("style", "text-properties"), attrib=theAttr)
# Add Standard Paragraph Style # Add Standard Paragraph Style
# ============================ # ============================
@@ -785,13 +776,13 @@ class ToOdt(Tokenizer):
theAttr[_mkTag("style", "name")] = "Standard" theAttr[_mkTag("style", "name")] = "Standard"
theAttr[_mkTag("style", "family")] = "paragraph" theAttr[_mkTag("style", "family")] = "paragraph"
theAttr[_mkTag("style", "class")] = "text" theAttr[_mkTag("style", "class")] = "text"
xStyl = etree.SubElement(self._xStyl, _mkTag("style", "style"), attrib=theAttr) xStyl = ET.SubElement(self._xStyl, _mkTag("style", "style"), attrib=theAttr)
theAttr = {} theAttr = {}
theAttr[_mkTag("style", "font-name")] = self._textFont theAttr[_mkTag("style", "font-name")] = self._textFont
theAttr[_mkTag("fo", "font-family")] = self._fontFamily theAttr[_mkTag("fo", "font-family")] = self._fontFamily
theAttr[_mkTag("fo", "font-size")] = self._fSizeText theAttr[_mkTag("fo", "font-size")] = self._fSizeText
etree.SubElement(xStyl, _mkTag("style", "text-properties"), attrib=theAttr) ET.SubElement(xStyl, _mkTag("style", "text-properties"), attrib=theAttr)
# Add Default Heading Style # Add Default Heading Style
# ========================= # =========================
@@ -802,19 +793,19 @@ class ToOdt(Tokenizer):
theAttr[_mkTag("style", "parent-style-name")] = "Standard" theAttr[_mkTag("style", "parent-style-name")] = "Standard"
theAttr[_mkTag("style", "next-style-name")] = "Text_20_body" theAttr[_mkTag("style", "next-style-name")] = "Text_20_body"
theAttr[_mkTag("style", "class")] = "text" theAttr[_mkTag("style", "class")] = "text"
xStyl = etree.SubElement(self._xStyl, _mkTag("style", "style"), attrib=theAttr) xStyl = ET.SubElement(self._xStyl, _mkTag("style", "style"), attrib=theAttr)
theAttr = {} theAttr = {}
theAttr[_mkTag("fo", "margin-top")] = self._mTopHead theAttr[_mkTag("fo", "margin-top")] = self._mTopHead
theAttr[_mkTag("fo", "margin-bottom")] = self._mBotHead theAttr[_mkTag("fo", "margin-bottom")] = self._mBotHead
theAttr[_mkTag("fo", "keep-with-next")] = "always" theAttr[_mkTag("fo", "keep-with-next")] = "always"
etree.SubElement(xStyl, _mkTag("style", "paragraph-properties"), attrib=theAttr) ET.SubElement(xStyl, _mkTag("style", "paragraph-properties"), attrib=theAttr)
theAttr = {} theAttr = {}
theAttr[_mkTag("style", "font-name")] = self._textFont theAttr[_mkTag("style", "font-name")] = self._textFont
theAttr[_mkTag("fo", "font-family")] = self._fontFamily theAttr[_mkTag("fo", "font-family")] = self._fontFamily
theAttr[_mkTag("fo", "font-size")] = self._fSizeHead theAttr[_mkTag("fo", "font-size")] = self._fSizeHead
etree.SubElement(xStyl, _mkTag("style", "text-properties"), attrib=theAttr) ET.SubElement(xStyl, _mkTag("style", "text-properties"), attrib=theAttr)
# Add Header and Footer Styles # Add Header and Footer Styles
# ============================ # ============================
@@ -824,7 +815,7 @@ class ToOdt(Tokenizer):
theAttr[_mkTag("style", "family")] = "paragraph" theAttr[_mkTag("style", "family")] = "paragraph"
theAttr[_mkTag("style", "parent-style-name")] = "Standard" theAttr[_mkTag("style", "parent-style-name")] = "Standard"
theAttr[_mkTag("style", "class")] = "extra" theAttr[_mkTag("style", "class")] = "extra"
etree.SubElement(self._xStyl, _mkTag("style", "style"), attrib=theAttr) ET.SubElement(self._xStyl, _mkTag("style", "style"), attrib=theAttr)
return return
@@ -989,23 +980,23 @@ class ToOdt(Tokenizer):
theAttr = {} theAttr = {}
theAttr[_mkTag("style", "name")] = "Standard" theAttr[_mkTag("style", "name")] = "Standard"
theAttr[_mkTag("style", "page-layout-name")] = "PM1" theAttr[_mkTag("style", "page-layout-name")] = "PM1"
xPage = etree.SubElement(self._xMast, _mkTag("style", "master-page"), attrib=theAttr) xPage = ET.SubElement(self._xMast, _mkTag("style", "master-page"), attrib=theAttr)
# Standard Page Header # Standard Page Header
xHead = etree.SubElement(xPage, _mkTag("style", "header")) xHead = ET.SubElement(xPage, _mkTag("style", "header"))
xPar = etree.SubElement(xHead, _mkTag("text", "p"), attrib={ xPar = ET.SubElement(xHead, _mkTag("text", "p"), attrib={
_mkTag("text", "style-name"): "Header" _mkTag("text", "style-name"): "Header"
}) })
xPar.text = self._headerText.strip() + " " xPar.text = self._headerText.strip() + " "
xTail = etree.SubElement(xPar, _mkTag("text", "page-number"), attrib={ xTail = ET.SubElement(xPar, _mkTag("text", "page-number"), attrib={
_mkTag("text", "select-page"): "current" _mkTag("text", "select-page"): "current"
}) })
xTail.text = "2" xTail.text = "2"
# First Page Header # First Page Header
xHead = etree.SubElement(xPage, _mkTag("style", "header-first")) xHead = ET.SubElement(xPage, _mkTag("style", "header-first"))
xPar = etree.SubElement(xHead, _mkTag("text", "p"), attrib={ xPar = ET.SubElement(xHead, _mkTag("text", "p"), attrib={
_mkTag("text", "style-name"): "Header" _mkTag("text", "style-name"): "Header"
}) })
@@ -1209,7 +1200,7 @@ class ODTParagraphStyle:
if aVal is not None: if aVal is not None:
theAttr[_mkTag(aNm, aName)] = aVal theAttr[_mkTag(aNm, aName)] = aVal
xEntry = etree.SubElement(xParent, _mkTag("style", "style"), attrib=theAttr) xEntry = ET.SubElement(xParent, _mkTag("style", "style"), attrib=theAttr)
theAttr = {} theAttr = {}
for aName, (aNm, aVal) in self._pAttr.items(): for aName, (aNm, aVal) in self._pAttr.items():
@@ -1217,7 +1208,7 @@ class ODTParagraphStyle:
theAttr[_mkTag(aNm, aName)] = aVal theAttr[_mkTag(aNm, aName)] = aVal
if theAttr: if theAttr:
etree.SubElement(xEntry, _mkTag("style", "paragraph-properties"), attrib=theAttr) ET.SubElement(xEntry, _mkTag("style", "paragraph-properties"), attrib=theAttr)
theAttr = {} theAttr = {}
for aName, (aNm, aVal) in self._tAttr.items(): for aName, (aNm, aVal) in self._tAttr.items():
@@ -1225,7 +1216,7 @@ class ODTParagraphStyle:
theAttr[_mkTag(aNm, aName)] = aVal theAttr[_mkTag(aNm, aName)] = aVal
if theAttr: if theAttr:
etree.SubElement(xEntry, _mkTag("style", "text-properties"), attrib=theAttr) ET.SubElement(xEntry, _mkTag("style", "text-properties"), attrib=theAttr)
return return
@@ -1296,7 +1287,7 @@ class ODTTextStyle:
theAttr = {} theAttr = {}
theAttr[_mkTag("style", "name")] = xName theAttr[_mkTag("style", "name")] = xName
theAttr[_mkTag("style", "family")] = "text" theAttr[_mkTag("style", "family")] = "text"
xEntry = etree.SubElement(xParent, _mkTag("style", "style"), attrib=theAttr) xEntry = ET.SubElement(xParent, _mkTag("style", "style"), attrib=theAttr)
theAttr = {} theAttr = {}
for aName, (aNm, aVal) in self._tAttr.items(): for aName, (aNm, aVal) in self._tAttr.items():
@@ -1304,7 +1295,7 @@ class ODTTextStyle:
theAttr[_mkTag(aNm, aName)] = aVal theAttr[_mkTag(aNm, aName)] = aVal
if theAttr: if theAttr:
etree.SubElement(xEntry, _mkTag("style", "text-properties"), attrib=theAttr) ET.SubElement(xEntry, _mkTag("style", "text-properties"), attrib=theAttr)
return return
@@ -1377,26 +1368,26 @@ class XMLParagraph:
if c == "\n": if c == "\n":
if self._nState in (X_ROOT_TEXT, X_ROOT_TAIL): if self._nState in (X_ROOT_TEXT, X_ROOT_TAIL):
self._xTail = etree.SubElement(self._xRoot, TAG_BR) self._xTail = ET.SubElement(self._xRoot, TAG_BR)
self._xTail.tail = "" self._xTail.tail = ""
self._nState = X_ROOT_TAIL self._nState = X_ROOT_TAIL
self._chrPos += 1 self._chrPos += 1
elif self._nState in (X_SPAN_TEXT, X_SPAN_SING): elif self._nState in (X_SPAN_TEXT, X_SPAN_SING):
self._xSing = etree.SubElement(self._xTail, TAG_BR) self._xSing = ET.SubElement(self._xTail, TAG_BR)
self._xSing.tail = "" self._xSing.tail = ""
self._nState = X_SPAN_SING self._nState = X_SPAN_SING
self._chrPos += 1 self._chrPos += 1
elif c == "\t": elif c == "\t":
if self._nState in (X_ROOT_TEXT, X_ROOT_TAIL): if self._nState in (X_ROOT_TEXT, X_ROOT_TAIL):
self._xTail = etree.SubElement(self._xRoot, TAG_TAB) self._xTail = ET.SubElement(self._xRoot, TAG_TAB)
self._xTail.tail = "" self._xTail.tail = ""
self._nState = X_ROOT_TAIL self._nState = X_ROOT_TAIL
self._chrPos += 1 self._chrPos += 1
elif self._nState in (X_SPAN_TEXT, X_SPAN_SING): elif self._nState in (X_SPAN_TEXT, X_SPAN_SING):
self._xSing = etree.SubElement(self._xTail, TAG_TAB) self._xSing = ET.SubElement(self._xTail, TAG_TAB)
self._xSing.tail = "" self._xSing.tail = ""
self._chrPos += 1 self._chrPos += 1
self._nState = X_SPAN_SING self._nState = X_SPAN_SING
@@ -1426,7 +1417,7 @@ class XMLParagraph:
Therefore we return to the root element level when we're done Therefore we return to the root element level when we're done
processing the text of the span. processing the text of the span.
""" """
self._xTail = etree.SubElement(self._xRoot, TAG_SPAN, attrib={ self._xTail = ET.SubElement(self._xRoot, TAG_SPAN, attrib={
TAG_STNM: tFmt TAG_STNM: tFmt
}) })
self._xTail.text = "" # Defaults to None self._xTail.text = "" # Defaults to None
@@ -1478,20 +1469,20 @@ class XMLParagraph:
if nSpaces == 2: if nSpaces == 2:
if self._nState in (X_ROOT_TEXT, X_ROOT_TAIL): if self._nState in (X_ROOT_TEXT, X_ROOT_TAIL):
self._xTail = etree.SubElement(self._xRoot, TAG_SPC) self._xTail = ET.SubElement(self._xRoot, TAG_SPC)
self._xTail.tail = "" self._xTail.tail = ""
self._nState = X_ROOT_TAIL self._nState = X_ROOT_TAIL
self._chrPos += nSpaces - 1 self._chrPos += nSpaces - 1
elif self._nState in (X_SPAN_TEXT, X_SPAN_SING): elif self._nState in (X_SPAN_TEXT, X_SPAN_SING):
self._xSing = etree.SubElement(self._xTail, TAG_SPC) self._xSing = ET.SubElement(self._xTail, TAG_SPC)
self._xSing.tail = "" self._xSing.tail = ""
self._nState = X_SPAN_SING self._nState = X_SPAN_SING
self._chrPos += nSpaces - 1 self._chrPos += nSpaces - 1
elif nSpaces > 2: elif nSpaces > 2:
if self._nState in (X_ROOT_TEXT, X_ROOT_TAIL): if self._nState in (X_ROOT_TEXT, X_ROOT_TAIL):
self._xTail = etree.SubElement(self._xRoot, TAG_SPC, attrib={ self._xTail = ET.SubElement(self._xRoot, TAG_SPC, attrib={
TAG_NSPC: str(nSpaces - 1) TAG_NSPC: str(nSpaces - 1)
}) })
self._xTail.tail = "" self._xTail.tail = ""
@@ -1499,7 +1490,7 @@ class XMLParagraph:
self._chrPos += nSpaces - 1 self._chrPos += nSpaces - 1
elif self._nState in (X_SPAN_TEXT, X_SPAN_SING): elif self._nState in (X_SPAN_TEXT, X_SPAN_SING):
self._xSing = etree.SubElement(self._xTail, TAG_SPC, attrib={ self._xSing = ET.SubElement(self._xTail, TAG_SPC, attrib={
TAG_NSPC: str(nSpaces - 1) TAG_NSPC: str(nSpaces - 1)
}) })
self._xSing.tail = "" self._xSing.tail = ""