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 xml.etree.ElementTree as ET
from lxml import etree
from hashlib import sha256
from zipfile import ZipFile
from datetime import datetime
from novelwriter import __version__
from novelwriter.common import xmlIndent
from novelwriter.constants import nwKeyWords, nwLabels
from novelwriter.core.tokenizer import Tokenizer, stripEscape
@@ -38,30 +39,27 @@ logger = logging.getLogger(__name__)
# Main XML NameSpaces
XML_NS = {
"office": "urn:oasis:names:tc:opendocument:xmlns:office:1.0",
"style": "urn:oasis:names:tc:opendocument:xmlns:style:1.0",
"loext": "urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0",
"text": "urn:oasis:names:tc:opendocument:xmlns:text:1.0",
"meta": "urn:oasis:names:tc:opendocument:xmlns:meta:1.0",
"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",
"manifest": "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0",
"office": "urn:oasis:names:tc:opendocument:xmlns:office:1.0",
"style": "urn:oasis:names:tc:opendocument:xmlns:style:1.0",
"loext": "urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0",
"text": "urn:oasis:names:tc:opendocument:xmlns:text:1.0",
"meta": "urn:oasis:names:tc:opendocument:xmlns:meta:1.0",
"fo": "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0",
"dc": "http://purl.org/dc/elements/1.1/",
}
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.
"""
theNS = nsMap.get(nsName, "")
if theNS:
return f"{{{theNS}}}{tagName}"
logger.warning("Missing xml namespace '%s'", nsName)
return tagName
uri = XML_NS.get(ns, "")
if uri:
return f"{{{uri}}}{tag}"
logger.warning("Missing xml namespace '%s'", ns)
return tag
# Mimetype and Version
@@ -284,16 +282,16 @@ class ToOdt(Tokenizer):
tAttr[_mkTag("office", "mimetype")] = X_MIME
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._xFont = etree.SubElement(self._dFlat, _mkTag("office", "font-face-decls"))
self._xStyl = etree.SubElement(self._dFlat, _mkTag("office", "styles"))
self._xAuto = etree.SubElement(self._dFlat, _mkTag("office", "automatic-styles"))
self._xMast = etree.SubElement(self._dFlat, _mkTag("office", "master-styles"))
self._xBody = etree.SubElement(self._dFlat, _mkTag("office", "body"))
self._xMeta = ET.SubElement(self._dFlat, _mkTag("office", "meta"))
self._xFont = ET.SubElement(self._dFlat, _mkTag("office", "font-face-decls"))
self._xStyl = ET.SubElement(self._dFlat, _mkTag("office", "styles"))
self._xAuto = ET.SubElement(self._dFlat, _mkTag("office", "automatic-styles"))
self._xMast = ET.SubElement(self._dFlat, _mkTag("office", "master-styles"))
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:
@@ -305,59 +303,59 @@ class ToOdt(Tokenizer):
tStyl = _mkTag("office", "document-styles")
# content.xml
self._dCont = etree.Element(tCont, attrib=tAttr, nsmap=XML_NS)
self._xFont = etree.SubElement(self._dCont, _mkTag("office", "font-face-decls"))
self._xAuto = etree.SubElement(self._dCont, _mkTag("office", "automatic-styles"))
self._xBody = etree.SubElement(self._dCont, _mkTag("office", "body"))
self._dCont = ET.Element(tCont, attrib=tAttr)
self._xFont = ET.SubElement(self._dCont, _mkTag("office", "font-face-decls"))
self._xAuto = ET.SubElement(self._dCont, _mkTag("office", "automatic-styles"))
self._xBody = ET.SubElement(self._dCont, _mkTag("office", "body"))
# meta.xml
self._dMeta = etree.Element(tMeta, attrib=tAttr, nsmap=XML_NS)
self._xMeta = etree.SubElement(self._dMeta, _mkTag("office", "meta"))
self._dMeta = ET.Element(tMeta, attrib=tAttr)
self._xMeta = ET.SubElement(self._dMeta, _mkTag("office", "meta"))
# styles.xml
self._dStyl = etree.Element(tStyl, attrib=tAttr, nsmap=XML_NS)
self._xFnt2 = etree.SubElement(self._dStyl, _mkTag("office", "font-face-decls"))
self._xStyl = etree.SubElement(self._dStyl, _mkTag("office", "styles"))
self._xAut2 = etree.SubElement(self._dStyl, _mkTag("office", "automatic-styles"))
self._xMast = etree.SubElement(self._dStyl, _mkTag("office", "master-styles"))
self._dStyl = ET.Element(tStyl, attrib=tAttr)
self._xFnt2 = ET.SubElement(self._dStyl, _mkTag("office", "font-face-decls"))
self._xStyl = ET.SubElement(self._dStyl, _mkTag("office", "styles"))
self._xAut2 = ET.SubElement(self._dStyl, _mkTag("office", "automatic-styles"))
self._xMast = ET.SubElement(self._dStyl, _mkTag("office", "master-styles"))
etree.SubElement(self._xFont, _mkTag("style", "font-face"), attrib=fAttr)
etree.SubElement(self._xFnt2, _mkTag("style", "font-face"), attrib=fAttr)
ET.SubElement(self._xFont, _mkTag("style", "font-face"), attrib=fAttr)
ET.SubElement(self._xFnt2, _mkTag("style", "font-face"), attrib=fAttr)
# 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")
# 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 = etree.SubElement(self._xMeta, _mkTag("meta", "generator"))
xMeta = ET.SubElement(self._xMeta, _mkTag("meta", "generator"))
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 = etree.SubElement(self._xMeta, _mkTag("meta", "editing-cycles"))
xMeta = ET.SubElement(self._xMeta, _mkTag("meta", "editing-cycles"))
xMeta.text = str(self.theProject.data.saveCount)
# Format is: PnYnMnDTnHnMnS
# https://www.w3.org/TR/2004/REC-xmlschema-2-20041028/#duration
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"
# 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 = etree.SubElement(self._xMeta, _mkTag("dc", "date"))
xMeta = ET.SubElement(self._xMeta, _mkTag("dc", "date"))
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
self._pageStyles()
@@ -503,51 +501,44 @@ class ToOdt(Tokenizer):
"""Save the data to an .fodt file.
"""
with open(savePath, mode="wb") as outFile:
outFile.write(etree.tostring(
self._dFlat,
pretty_print=True,
encoding="utf-8",
xml_declaration=True
))
xml = ET.ElementTree(self._dFlat)
xmlIndent(xml, space=" ")
xml.write(outFile, encoding="utf-8", xml_declaration=True)
return
def saveOpenDocText(self, savePath):
"""Save the data to an .odt file.
"""
mMani = _mkTag("manifest", "manifest", nsMap=MANI_NS)
mVers = _mkTag("manifest", "version", nsMap=MANI_NS)
mPath = _mkTag("manifest", "full-path", nsMap=MANI_NS)
mType = _mkTag("manifest", "media-type", nsMap=MANI_NS)
mFile = _mkTag("manifest", "file-entry", nsMap=MANI_NS)
mMani = _mkTag("manifest", "manifest")
mVers = _mkTag("manifest", "version")
mPath = _mkTag("manifest", "full-path")
mType = _mkTag("manifest", "media-type")
mFile = _mkTag("manifest", "file-entry")
xMani = etree.Element(mMani, attrib={mVers: X_VERS}, nsmap=MANI_NS)
etree.SubElement(xMani, mFile, attrib={mPath: "/", mVers: X_VERS, mType: X_MIME})
etree.SubElement(xMani, mFile, attrib={mPath: "settings.xml", mType: "text/xml"})
etree.SubElement(xMani, mFile, attrib={mPath: "content.xml", mType: "text/xml"})
etree.SubElement(xMani, mFile, attrib={mPath: "meta.xml", mType: "text/xml"})
etree.SubElement(xMani, mFile, attrib={mPath: "styles.xml", mType: "text/xml"})
xMani = ET.Element(mMani, attrib={mVers: X_VERS})
ET.SubElement(xMani, mFile, attrib={mPath: "/", mVers: X_VERS, mType: X_MIME})
ET.SubElement(xMani, mFile, attrib={mPath: "settings.xml", mType: "text/xml"})
ET.SubElement(xMani, mFile, attrib={mPath: "content.xml", mType: "text/xml"})
ET.SubElement(xMani, mFile, attrib={mPath: "meta.xml", mType: "text/xml"})
ET.SubElement(xMani, mFile, attrib={mPath: "styles.xml", mType: "text/xml"})
oRoot = _mkTag("office", "document-settings", nsMap=OFFICE_NS)
oVers = _mkTag("office", "version", nsMap=OFFICE_NS)
xSett = etree.Element(oRoot, nsmap=OFFICE_NS, attrib={oVers: X_VERS})
oRoot = _mkTag("office", "document-settings")
oVers = _mkTag("office", "version")
xSett = ET.Element(oRoot, attrib={oVers: X_VERS})
with ZipFile(savePath, mode="w") as outFile:
outFile.writestr("mimetype", X_MIME)
outFile.writestr("META-INF/manifest.xml", etree.tostring(
xMani, pretty_print=False, encoding="utf-8", xml_declaration=True
))
outFile.writestr("settings.xml", etree.tostring(
xSett, pretty_print=False, encoding="utf-8", xml_declaration=True
))
outFile.writestr("content.xml", etree.tostring(
self._dCont, pretty_print=False, encoding="utf-8", xml_declaration=True
))
outFile.writestr("meta.xml", etree.tostring(
self._dMeta, pretty_print=False, encoding="utf-8", xml_declaration=True
))
outFile.writestr("styles.xml", etree.tostring(
self._dStyl, pretty_print=False, encoding="utf-8", xml_declaration=True
))
def putInZip(name, xObj, zipObj):
with zipObj.open(name, mode="w") as fObj:
xml = ET.ElementTree(xObj)
xmlIndent(xml, space=" ")
xml.write(fObj, encoding="utf-8", xml_declaration=True)
with ZipFile(savePath, mode="w") as outZip:
outZip.writestr("mimetype", X_MIME)
putInZip("META-INF/manifest.xml", xMani, outZip)
putInZip("settings.xml", xSett, outZip)
putInZip("content.xml", self._dCont, outZip)
putInZip("meta.xml", self._dMeta, outZip)
putInZip("styles.xml", self._dStyl, outZip)
return
@@ -604,7 +595,7 @@ class ToOdt(Tokenizer):
tAttr[_mkTag("text", "outline-level")] = oLevel
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
# lxml will add a line break if the first subelement is a span.
@@ -732,25 +723,25 @@ class ToOdt(Tokenizer):
theAttr = {}
theAttr[_mkTag("style", "name")] = "PM1"
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:
xPage = etree.SubElement(self._xAut2, _mkTag("style", "page-layout"), attrib=theAttr)
xPage = ET.SubElement(self._xAut2, _mkTag("style", "page-layout"), attrib=theAttr)
theAttr = {}
theAttr[_mkTag("fo", "margin-top")] = self._mDocTop
theAttr[_mkTag("fo", "margin-bottom")] = self._mDocBtm
theAttr[_mkTag("fo", "margin-left")] = self._mDocLeft
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[_mkTag("fo", "min-height")] = "0.600cm"
theAttr[_mkTag("fo", "margin-left")] = "0.000cm"
theAttr[_mkTag("fo", "margin-right")] = "0.000cm"
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
@@ -762,13 +753,13 @@ class ToOdt(Tokenizer):
theAttr = {}
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[_mkTag("style", "line-break")] = "strict"
theAttr[_mkTag("style", "tab-stop-distance")] = "1.251cm"
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[_mkTag("style", "font-name")] = self._textFont
@@ -776,7 +767,7 @@ class ToOdt(Tokenizer):
theAttr[_mkTag("fo", "font-size")] = self._fSizeText
theAttr[_mkTag("fo", "language")] = self._dLanguage
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
# ============================
@@ -785,13 +776,13 @@ class ToOdt(Tokenizer):
theAttr[_mkTag("style", "name")] = "Standard"
theAttr[_mkTag("style", "family")] = "paragraph"
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[_mkTag("style", "font-name")] = self._textFont
theAttr[_mkTag("fo", "font-family")] = self._fontFamily
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
# =========================
@@ -802,19 +793,19 @@ class ToOdt(Tokenizer):
theAttr[_mkTag("style", "parent-style-name")] = "Standard"
theAttr[_mkTag("style", "next-style-name")] = "Text_20_body"
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[_mkTag("fo", "margin-top")] = self._mTopHead
theAttr[_mkTag("fo", "margin-bottom")] = self._mBotHead
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[_mkTag("style", "font-name")] = self._textFont
theAttr[_mkTag("fo", "font-family")] = self._fontFamily
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
# ============================
@@ -824,7 +815,7 @@ class ToOdt(Tokenizer):
theAttr[_mkTag("style", "family")] = "paragraph"
theAttr[_mkTag("style", "parent-style-name")] = "Standard"
theAttr[_mkTag("style", "class")] = "extra"
etree.SubElement(self._xStyl, _mkTag("style", "style"), attrib=theAttr)
ET.SubElement(self._xStyl, _mkTag("style", "style"), attrib=theAttr)
return
@@ -989,23 +980,23 @@ class ToOdt(Tokenizer):
theAttr = {}
theAttr[_mkTag("style", "name")] = "Standard"
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
xHead = etree.SubElement(xPage, _mkTag("style", "header"))
xPar = etree.SubElement(xHead, _mkTag("text", "p"), attrib={
xHead = ET.SubElement(xPage, _mkTag("style", "header"))
xPar = ET.SubElement(xHead, _mkTag("text", "p"), attrib={
_mkTag("text", "style-name"): "Header"
})
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"
})
xTail.text = "2"
# First Page Header
xHead = etree.SubElement(xPage, _mkTag("style", "header-first"))
xPar = etree.SubElement(xHead, _mkTag("text", "p"), attrib={
xHead = ET.SubElement(xPage, _mkTag("style", "header-first"))
xPar = ET.SubElement(xHead, _mkTag("text", "p"), attrib={
_mkTag("text", "style-name"): "Header"
})
@@ -1209,7 +1200,7 @@ class ODTParagraphStyle:
if aVal is not None:
theAttr[_mkTag(aNm, aName)] = aVal
xEntry = etree.SubElement(xParent, _mkTag("style", "style"), attrib=theAttr)
xEntry = ET.SubElement(xParent, _mkTag("style", "style"), attrib=theAttr)
theAttr = {}
for aName, (aNm, aVal) in self._pAttr.items():
@@ -1217,7 +1208,7 @@ class ODTParagraphStyle:
theAttr[_mkTag(aNm, aName)] = aVal
if theAttr:
etree.SubElement(xEntry, _mkTag("style", "paragraph-properties"), attrib=theAttr)
ET.SubElement(xEntry, _mkTag("style", "paragraph-properties"), attrib=theAttr)
theAttr = {}
for aName, (aNm, aVal) in self._tAttr.items():
@@ -1225,7 +1216,7 @@ class ODTParagraphStyle:
theAttr[_mkTag(aNm, aName)] = aVal
if theAttr:
etree.SubElement(xEntry, _mkTag("style", "text-properties"), attrib=theAttr)
ET.SubElement(xEntry, _mkTag("style", "text-properties"), attrib=theAttr)
return
@@ -1296,7 +1287,7 @@ class ODTTextStyle:
theAttr = {}
theAttr[_mkTag("style", "name")] = xName
theAttr[_mkTag("style", "family")] = "text"
xEntry = etree.SubElement(xParent, _mkTag("style", "style"), attrib=theAttr)
xEntry = ET.SubElement(xParent, _mkTag("style", "style"), attrib=theAttr)
theAttr = {}
for aName, (aNm, aVal) in self._tAttr.items():
@@ -1304,7 +1295,7 @@ class ODTTextStyle:
theAttr[_mkTag(aNm, aName)] = aVal
if theAttr:
etree.SubElement(xEntry, _mkTag("style", "text-properties"), attrib=theAttr)
ET.SubElement(xEntry, _mkTag("style", "text-properties"), attrib=theAttr)
return
@@ -1377,26 +1368,26 @@ class XMLParagraph:
if c == "\n":
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._nState = X_ROOT_TAIL
self._chrPos += 1
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._nState = X_SPAN_SING
self._chrPos += 1
elif c == "\t":
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._nState = X_ROOT_TAIL
self._chrPos += 1
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._chrPos += 1
self._nState = X_SPAN_SING
@@ -1426,7 +1417,7 @@ class XMLParagraph:
Therefore we return to the root element level when we're done
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
})
self._xTail.text = "" # Defaults to None
@@ -1478,20 +1469,20 @@ class XMLParagraph:
if nSpaces == 2:
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._nState = X_ROOT_TAIL
self._chrPos += nSpaces - 1
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._nState = X_SPAN_SING
self._chrPos += nSpaces - 1
elif nSpaces > 2:
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)
})
self._xTail.tail = ""
@@ -1499,7 +1490,7 @@ class XMLParagraph:
self._chrPos += nSpaces - 1
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)
})
self._xSing.tail = ""