From da2e40db4dca39e4db45c6f16bae7abeb86e431b Mon Sep 17 00:00:00 2001
From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com>
Date: Wed, 27 Jan 2021 01:12:09 +0100
Subject: [PATCH] Add ODT auto-style logic
---
nw/core/toodt.py | 478 +++++++++++++++++++++--------
tests/test_core/test_core_toodt.py | 35 ++-
2 files changed, 383 insertions(+), 130 deletions(-)
diff --git a/nw/core/toodt.py b/nw/core/toodt.py
index 09fbb91f..c89c065d 100644
--- a/nw/core/toodt.py
+++ b/nw/core/toodt.py
@@ -29,6 +29,7 @@ import logging
import os
from lxml import etree
+from hashlib import sha256
from nw.core.tokenizer import Tokenizer
@@ -39,7 +40,6 @@ XML_NS = {
"style" : "urn:oasis:names:tc:opendocument:xmlns:style:1.0",
"text" : "urn:oasis:names:tc:opendocument:xmlns:text:1.0",
"fo" : "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0",
- "loext" : "urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0",
}
class ToOdt(Tokenizer):
@@ -51,7 +51,13 @@ class ToOdt(Tokenizer):
self._xRoot = None
self._xStyl = None
+ self._xBody = None
self._xText = None
+ self._xAuto = None
+
+ self._mainPara = {}
+ self._autoPara = {}
+ self._autoText = {}
self._dLanguage = "en"
self._dCountry = "GB"
@@ -97,11 +103,13 @@ class ToOdt(Tokenizer):
}
self._xRoot = etree.Element(_mkTag("office", "document"), attrib=rAttr, nsmap=XML_NS)
self._xStyl = etree.SubElement(self._xRoot, _mkTag("office", "styles"))
- self._xText = etree.SubElement(self._xRoot, _mkTag("office", "text"))
+ self._xAuto = etree.SubElement(self._xRoot, _mkTag("office", "automatic-styles"))
+ self._xBody = etree.SubElement(self._xRoot, _mkTag("office", "body"))
+ self._xText = etree.SubElement(self._xBody, _mkTag("office", "text"))
# Add Styles
- self._styleParagraph()
- self._styleHeaders()
+ self._defaultStyles()
+ self._useableStyles()
return
@@ -113,18 +121,60 @@ class ToOdt(Tokenizer):
for tType, tLine, tText, tFormat, tStyle in self.theTokens:
+ # Styles
+ oStyle = ODTParagraphStyle()
+ if tStyle is not None:
+ if tStyle & self.A_LEFT:
+ oStyle.setTextAlign("left")
+ if tStyle & self.A_RIGHT:
+ oStyle.setTextAlign("right")
+ if tStyle & self.A_CENTRE:
+ oStyle.setTextAlign("center")
+ if tStyle & self.A_JUSTIFY:
+ oStyle.setTextAlign("justify")
+ if tStyle & self.A_PBB:
+ oStyle.setBreakBefore("page")
+ if tStyle & self.A_PBA:
+ oStyle.setBreakAfter("page")
+
# Process Text Type
if tType == self.T_EMPTY:
continue
elif tType == self.T_TITLE:
- continue
+ tHead = tText.replace(r"\\", "
")
+ self._addTextPar("Title", oStyle, tHead)
+
+ elif tType == self.T_HEAD1:
+ tHead = tText.replace(r"\\", "
")
+ self._addTextPar("Heading_1", oStyle, tHead, oLevel="1")
+
+ elif tType == self.T_HEAD2:
+ tHead = tText.replace(r"\\", "
")
+ self._addTextPar("Heading_2", oStyle, tHead, oLevel="2")
+
+ elif tType == self.T_HEAD3:
+ tHead = tText.replace(r"\\", "
")
+ self._addTextPar("Heading_3", oStyle, tHead, oLevel="3")
+
+ elif tType == self.T_HEAD4:
+ tHead = tText.replace(r"\\", "
")
+ self._addTextPar("Heading_4", oStyle, tHead, oLevel="4")
+
+ elif tType == self.T_SEP:
+ self._addTextPar("Text_Body", oStyle, tText)
+
+ elif tType == self.T_SKIP:
+ self._addTextPar("Text_Body", oStyle, "")
return
def closeDocument(self):
"""Return the serialised XML document
"""
+ for styleName, styleObj in self._autoPara.values():
+ styleObj.packXML(self._xAuto, styleName)
+
self.theResult = etree.tostring(
self._xRoot,
pretty_print = True,
@@ -138,15 +188,51 @@ class ToOdt(Tokenizer):
return
+ ##
+ # Internal Functions
+ ##
+
+ def _addTextPar(self, styleName, oStyle, theText, oLevel=None):
+ """Add a text paragraph to the text XML element.
+ """
+ tAttr = {}
+ tAttr[_mkTag("text", "style-name")] = self._paraStyle(styleName, oStyle)
+ if oLevel is not None:
+ tAttr[_mkTag("text", "outline-level")] = oLevel
+ xElem = etree.SubElement(self._xText, _mkTag("text", "p"), attrib=tAttr)
+ xElem.text = theText
+ return
+
+ def _paraStyle(self, parName, oStyle):
+ """Return a name for a style object.
+ """
+ refStyle = self._mainPara.get(parName, None)
+ if refStyle is None:
+ logger.error("Unknown paragraph style '%s'" % parName)
+ return "Standard"
+
+ if not refStyle.checkNew(oStyle):
+ return parName
+
+ oStyle.setParentStyleName(parName)
+ theID = oStyle.getID()
+ if theID in self._autoPara:
+ return self._autoPara[theID][0]
+
+ newName = "P%d" % (len(self._autoPara) + 1)
+ self._autoPara[theID] = (newName, oStyle)
+
+ return newName
+
##
# Style Elements
##
- def _styleParagraph(self):
- """Set the paragraph styles.
+ def _defaultStyles(self):
+ """Set the default styles.
"""
- # Add Default Paragraph Style
- # ===========================
+ # Add Paragraph Family Style
+ # ==========================
theAttr = {}
theAttr[_mkTag("style", "family")] = "paragraph"
@@ -165,8 +251,8 @@ class ToOdt(Tokenizer):
theAttr[_mkTag("fo", "country")] = self._dCountry
etree.SubElement(xStyl, _mkTag("style", "text-properties"), attrib=theAttr)
- # Add Paragraph Style
- # ===================
+ # Add Standard Paragraph Style
+ # ============================
theAttr = {}
theAttr[_mkTag("style", "name")] = "Standard"
@@ -174,29 +260,6 @@ class ToOdt(Tokenizer):
theAttr[_mkTag("style", "class")] = "text"
etree.SubElement(self._xStyl, _mkTag("style", "style"), attrib=theAttr)
- # Add Text Body Style
- # ===================
-
- theAttr = {}
- theAttr[_mkTag("style", "name")] = "Text_body"
- theAttr[_mkTag("style", "display-name")] = "Text Body"
- theAttr[_mkTag("style", "family")] = "paragraph"
- theAttr[_mkTag("style", "parent-style-name")] = "Standard"
- theAttr[_mkTag("style", "class")] = "text"
- xStyl = etree.SubElement(self._xStyl, _mkTag("style", "style"), attrib=theAttr)
-
- theAttr = {}
- theAttr[_mkTag("fo", "margin-top")] = "0cm"
- theAttr[_mkTag("fo", "margin-bottom")] = "0.247cm"
- theAttr[_mkTag("style", "contextual-spacing")] = "false"
- theAttr[_mkTag("fo", "line-height")] = "115%"
- etree.SubElement(xStyl, _mkTag("style", "paragraph-properties"), attrib=theAttr)
-
- return
-
- def _styleHeaders(self):
- """Set the header styles.
- """
# Add Default Heading Style
# =========================
@@ -204,14 +267,13 @@ class ToOdt(Tokenizer):
theAttr[_mkTag("style", "name")] = "Heading"
theAttr[_mkTag("style", "family")] = "paragraph"
theAttr[_mkTag("style", "parent-style-name")] = "Standard"
- theAttr[_mkTag("style", "next-style-name")] = "Text_body"
+ theAttr[_mkTag("style", "next-style-name")] = "Text_Body"
theAttr[_mkTag("style", "class")] = "text"
xStyl = etree.SubElement(self._xStyl, _mkTag("style", "style"), attrib=theAttr)
theAttr = {}
theAttr[_mkTag("fo", "margin-top")] = "0.423cm"
theAttr[_mkTag("fo", "margin-bottom")] = "0.212cm"
- theAttr[_mkTag("style", "contextual-spacing")] = "false"
theAttr[_mkTag("fo", "keep-with-next")] = "always"
etree.SubElement(xStyl, _mkTag("style", "paragraph-properties"), attrib=theAttr)
@@ -222,129 +284,287 @@ class ToOdt(Tokenizer):
theAttr[_mkTag("fo", "font-size")] = "14pt"
etree.SubElement(xStyl, _mkTag("style", "text-properties"), attrib=theAttr)
+ return
+
+ def _useableStyles(self):
+ """Set the usable styles.
+ """
+ # Add Text Body Style
+ # ===================
+
+ oStyle = ODTParagraphStyle()
+ oStyle.setDisplayName("Text Body")
+ oStyle.setParentStyleName("Standard")
+ oStyle.setClass("text")
+ oStyle.setMarginTop("0cm")
+ oStyle.setMarginBottom("0.247cm")
+ oStyle.setLineHeight("115%")
+ oStyle.packXML(self._xStyl, "Text_Body")
+
+ self._mainPara["Text_Body"] = oStyle
+
# Add Title Style
# ===============
- theAttr = {}
- theAttr[_mkTag("style", "name")] = "Title"
- theAttr[_mkTag("style", "family")] = "paragraph"
- theAttr[_mkTag("style", "parent-style-name")] = "Heading"
- theAttr[_mkTag("style", "next-style-name")] = "Text_body"
- theAttr[_mkTag("style", "class")] = "chapter"
- xStyl = etree.SubElement(self._xStyl, _mkTag("style", "style"), attrib=theAttr)
+ oStyle = ODTParagraphStyle()
+ oStyle.setDisplayName("Title")
+ oStyle.setParentStyleName("Heading")
+ oStyle.setNextStyleName("Text_Body")
+ oStyle.setClass("chapter")
+ oStyle.setTextAlign("center")
+ oStyle.setFontSize("28pt")
+ oStyle.setFontWeight("bold")
+ oStyle.packXML(self._xStyl, "Title")
- theAttr = {}
- theAttr[_mkTag("fo", "text-align")] = "center"
- etree.SubElement(xStyl, _mkTag("style", "paragraph-properties"), attrib=theAttr)
-
- theAttr = {}
- theAttr[_mkTag("fo", "font-size")] = "28pt"
- theAttr[_mkTag("fo", "font-weight")] = "bold"
- etree.SubElement(xStyl, _mkTag("style", "text-properties"), attrib=theAttr)
+ self._mainPara["Title"] = oStyle
# Add Heading 1 Style
# ===================
- theAttr = {}
- theAttr[_mkTag("style", "name")] = "Heading_1"
- theAttr[_mkTag("style", "display-name")] = "Heading 1"
- theAttr[_mkTag("style", "family")] = "paragraph"
- theAttr[_mkTag("style", "parent-style-name")] = "Heading"
- theAttr[_mkTag("style", "next-style-name")] = "Text_body"
- theAttr[_mkTag("style", "default-outline-level")] = "1"
- theAttr[_mkTag("style", "class")] = "text"
- xStyl = etree.SubElement(self._xStyl, _mkTag("style", "style"), attrib=theAttr)
+ oStyle = ODTParagraphStyle()
+ oStyle.setDisplayName("Heading 1")
+ oStyle.setParentStyleName("Heading")
+ oStyle.setNextStyleName("Text_Body")
+ oStyle.setOutlineLevel("1")
+ oStyle.setClass("text")
+ oStyle.setMarginTop("0.423cm")
+ oStyle.setMarginBottom("0.212cm")
+ oStyle.setFontSize("200%")
+ oStyle.setFontWeight("bold")
+ oStyle.packXML(self._xStyl, "Heading_1")
- theAttr = {}
- theAttr[_mkTag("fo", "margin-top")] = "0.423cm"
- theAttr[_mkTag("fo", "margin-bottom")] = "0.212cm"
- theAttr[_mkTag("style", "contextual-spacing")] = "false"
- etree.SubElement(xStyl, _mkTag("style", "paragraph-properties"), attrib=theAttr)
-
- theAttr = {}
- theAttr[_mkTag("fo", "font-size")] = "130%"
- theAttr[_mkTag("fo", "font-weight")] = "bold"
- etree.SubElement(xStyl, _mkTag("style", "text-properties"), attrib=theAttr)
+ self._mainPara["Heading_1"] = oStyle
# Add Heading 2 Style
# ===================
- theAttr = {}
- theAttr[_mkTag("style", "name")] = "Heading_2"
- theAttr[_mkTag("style", "display-name")] = "Heading 2"
- theAttr[_mkTag("style", "family")] = "paragraph"
- theAttr[_mkTag("style", "parent-style-name")] = "Heading"
- theAttr[_mkTag("style", "next-style-name")] = "Text_body"
- theAttr[_mkTag("style", "default-outline-level")] = "2"
- theAttr[_mkTag("style", "class")] = "text"
- xStyl = etree.SubElement(self._xStyl, _mkTag("style", "style"), attrib=theAttr)
+ oStyle = ODTParagraphStyle()
+ oStyle.setDisplayName("Heading 2")
+ oStyle.setParentStyleName("Heading")
+ oStyle.setNextStyleName("Text_Body")
+ oStyle.setOutlineLevel("2")
+ oStyle.setClass("text")
+ oStyle.setMarginTop("0.353cm")
+ oStyle.setMarginBottom("0.212cm")
+ oStyle.setFontSize("140%")
+ oStyle.setFontWeight("bold")
+ oStyle.packXML(self._xStyl, "Heading_2")
- theAttr = {}
- theAttr[_mkTag("fo", "margin-top")] = "0.353cm"
- theAttr[_mkTag("fo", "margin-bottom")] = "0.212cm"
- theAttr[_mkTag("style", "contextual-spacing")] = "false"
- etree.SubElement(xStyl, _mkTag("style", "paragraph-properties"), attrib=theAttr)
-
- theAttr = {}
- theAttr[_mkTag("fo", "font-size")] = "120%"
- theAttr[_mkTag("fo", "font-weight")] = "bold"
- etree.SubElement(xStyl, _mkTag("style", "text-properties"), attrib=theAttr)
+ self._mainPara["Heading_2"] = oStyle
# Add Heading 3 Style
# ===================
- theAttr = {}
- theAttr[_mkTag("style", "name")] = "Heading_3"
- theAttr[_mkTag("style", "display-name")] = "Heading 3"
- theAttr[_mkTag("style", "family")] = "paragraph"
- theAttr[_mkTag("style", "parent-style-name")] = "Heading"
- theAttr[_mkTag("style", "next-style-name")] = "Text_body"
- theAttr[_mkTag("style", "default-outline-level")] = "3"
- theAttr[_mkTag("style", "class")] = "text"
- xStyl = etree.SubElement(self._xStyl, _mkTag("style", "style"), attrib=theAttr)
+ oStyle = ODTParagraphStyle()
+ oStyle.setDisplayName("Heading 3")
+ oStyle.setParentStyleName("Heading")
+ oStyle.setNextStyleName("Text_Body")
+ oStyle.setOutlineLevel("3")
+ oStyle.setClass("text")
+ oStyle.setMarginTop("0.247cm")
+ oStyle.setMarginBottom("0.212cm")
+ oStyle.setFontSize("125%")
+ oStyle.setFontWeight("bold")
+ oStyle.packXML(self._xStyl, "Heading_3")
- theAttr = {}
- theAttr[_mkTag("fo", "margin-top")] = "0.247cm"
- theAttr[_mkTag("fo", "margin-bottom")] = "0.212cm"
- theAttr[_mkTag("style", "contextual-spacing")] = "false"
- etree.SubElement(xStyl, _mkTag("style", "paragraph-properties"), attrib=theAttr)
-
- theAttr = {}
- theAttr[_mkTag("fo", "font-size")] = "110%"
- theAttr[_mkTag("fo", "font-weight")] = "bold"
- etree.SubElement(xStyl, _mkTag("style", "text-properties"), attrib=theAttr)
+ self._mainPara["Heading_3"] = oStyle
# Add Heading 4 Style
# ===================
- theAttr = {}
- theAttr[_mkTag("style", "name")] = "Heading_4"
- theAttr[_mkTag("style", "display-name")] = "Heading 4"
- theAttr[_mkTag("style", "family")] = "paragraph"
- theAttr[_mkTag("style", "parent-style-name")] = "Heading"
- theAttr[_mkTag("style", "next-style-name")] = "Text_body"
- theAttr[_mkTag("style", "default-outline-level")] = "4"
- theAttr[_mkTag("style", "class")] = "text"
- xStyl = etree.SubElement(self._xStyl, _mkTag("style", "style"), attrib=theAttr)
+ oStyle = ODTParagraphStyle()
+ oStyle.setDisplayName("Heading 4")
+ oStyle.setParentStyleName("Heading")
+ oStyle.setNextStyleName("Text_Body")
+ oStyle.setOutlineLevel("4")
+ oStyle.setClass("text")
+ oStyle.setMarginTop("0.247cm")
+ oStyle.setMarginBottom("0.212cm")
+ oStyle.setFontSize("110%")
+ oStyle.setFontWeight("bold")
+ oStyle.packXML(self._xStyl, "Heading_4")
- theAttr = {}
- theAttr[_mkTag("fo", "margin-top")] = "0.247cm"
- theAttr[_mkTag("fo", "margin-bottom")] = "0.212cm"
- theAttr[_mkTag("style", "contextual-spacing")] = "false"
- etree.SubElement(xStyl, _mkTag("style", "paragraph-properties"), attrib=theAttr)
-
- theAttr = {}
- theAttr[_mkTag("fo", "font-size")] = "100%"
- theAttr[_mkTag("fo", "font-weight")] = "bold"
- etree.SubElement(xStyl, _mkTag("style", "text-properties"), attrib=theAttr)
+ self._mainPara["Heading_4"] = oStyle
return
# END Class ToOdt
-# =========================================================================== #
+# =============================================================================================== #
+# Auto-Style Classes
+# =============================================================================================== #
+
+class ODTParagraphStyle():
+
+ VALID_ALIGN = ["start", "center", "end", "justify", "inside", "outside", "left", "right"]
+ VALID_BREAK = ["auto", "column", "page", "even-page", "odd-page", "inherit"]
+ VALID_LEVEL = ["1", "2", "3", "4"]
+ VALID_CLASS = ["text", "chapter"]
+ VALID_WEIGHT = ["normal", "inherit", "bold"]
+
+ def __init__(self):
+
+ # Attributes
+ self._mAttr = {
+ "display-name": ["style", None],
+ "parent-style-name": ["style", None],
+ "next-style-name": ["style", None],
+ "default-outline-level": ["style", None],
+ "class": ["style", None],
+ }
+
+ # Paragraph Attributes
+ self._pAttr = {
+ "margin-top": ["fo", None],
+ "margin-bottom": ["fo", None],
+ "line-height": ["fo", None],
+ "text-align": ["fo", None],
+ "break-before": ["fo", None],
+ "break-after": ["fo", None],
+ }
+
+ # text Attributes
+ self._tAttr = {
+ "font-size": ["fo", None],
+ "font-weight": ["fo", None],
+ }
+
+ return
+
+ ##
+ # Attribute Setters
+ ##
+
+ def setDisplayName(self, theValue):
+ self._mAttr["display-name"][1] = str(theValue)
+ return
+
+ def setParentStyleName(self, theValue):
+ self._mAttr["parent-style-name"][1] = str(theValue)
+ return
+
+ def setNextStyleName(self, theValue):
+ self._mAttr["next-style-name"][1] = str(theValue)
+ return
+
+ def setOutlineLevel(self, theValue):
+ if theValue in self.VALID_LEVEL:
+ self._mAttr["default-outline-level"][1] = str(theValue)
+ return
+
+ def setClass(self, theValue):
+ if theValue in self.VALID_CLASS:
+ self._mAttr["class"][1] = str(theValue)
+ return
+
+ ##
+ # Paragraph Setters
+ ##
+
+ def setMarginTop(self, theValue):
+ self._pAttr["margin-top"][1] = str(theValue)
+ return
+
+ def setMarginBottom(self, theValue):
+ self._pAttr["margin-bottom"][1] = str(theValue)
+ return
+
+ def setLineHeight(self, theValue):
+ self._pAttr["line-height"][1] = str(theValue)
+ return
+
+ def setTextAlign(self, theValue):
+ if theValue in self.VALID_ALIGN:
+ self._pAttr["text-align"][1] = str(theValue)
+ return
+
+ def setBreakBefore(self, theValue):
+ if theValue in self.VALID_BREAK:
+ self._pAttr["break-before"][1] = str(theValue)
+ return
+
+ def setBreakAfter(self, theValue):
+ if theValue in self.VALID_BREAK:
+ self._pAttr["break-after"][1] = str(theValue)
+ return
+
+ ##
+ # Text Setters
+ ##
+
+ def setFontSize(self, theValue):
+ self._tAttr["font-size"][1] = str(theValue)
+ return
+
+ def setFontWeight(self, theValue):
+ if theValue in self.VALID_WEIGHT:
+ self._tAttr["font-weight"][1] = str(theValue)
+ return
+
+ ##
+ # Methods
+ ##
+
+ def checkNew(self, refStyle):
+ """Check if there are new settings in refStyle that differ from
+ those in the current object.
+ """
+ for aName, (aNm, aVal) in refStyle._mAttr.items():
+ if aVal is not None and aVal != self._mAttr[aName][1]:
+ return True
+ for aName, (aNm, aVal) in refStyle._pAttr.items():
+ if aVal is not None and aVal != self._pAttr[aName][1]:
+ return True
+ for aName, (aNm, aVal) in refStyle._tAttr.items():
+ if aVal is not None and aVal != self._tAttr[aName][1]:
+ return True
+ return False
+
+ def getID(self):
+ """Generate a unique ID from the settings.
+ """
+ theString = (
+ f"Paragraph:Main:{str(self._mAttr)}:"
+ f"Paragraph:Para:{str(self._pAttr)}:"
+ f"Paragraph:Text:{str(self._tAttr)}:"
+ )
+ return sha256(theString.encode()).hexdigest()
+
+ def packXML(self, xParent, xName):
+ """Pack the content into an xml element.
+ """
+ theAttr = {}
+ theAttr[_mkTag("style", "name")] = xName
+ theAttr[_mkTag("style", "family")] = "paragraph"
+ for aName, (aNm, aVal) in self._mAttr.items():
+ if aVal is not None:
+ theAttr[_mkTag(aNm, aName)] = aVal
+
+ xEntry = etree.SubElement(xParent, _mkTag("style", "style"), attrib=theAttr)
+
+ theAttr = {}
+ for aName, (aNm, aVal) in self._pAttr.items():
+ if aVal is not None:
+ theAttr[_mkTag(aNm, aName)] = aVal
+
+ if theAttr:
+ etree.SubElement(xEntry, _mkTag("style", "paragraph-properties"), attrib=theAttr)
+
+ theAttr = {}
+ for aName, (aNm, aVal) in self._tAttr.items():
+ if aVal is not None:
+ theAttr[_mkTag(aNm, aName)] = aVal
+
+ if theAttr:
+ etree.SubElement(xEntry, _mkTag("style", "text-properties"), attrib=theAttr)
+
+ return
+
+# END Class ODTParagraphStyle
+
+# =============================================================================================== #
# Local Functions
-# =========================================================================== #
+# =============================================================================================== #
def _mkTag(nsName, tagName):
"""Assemble namespace and tag name.
diff --git a/tests/test_core/test_core_toodt.py b/tests/test_core/test_core_toodt.py
index 6159929a..c0e8c797 100644
--- a/tests/test_core/test_core_toodt.py
+++ b/tests/test_core/test_core_toodt.py
@@ -23,8 +23,25 @@ along with this program. If not, see .
import nw
import pytest
+from lxml import etree
+
from nw.core import NWProject, NWIndex, ToOdt
+XML_NS = [
+ ' xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"',
+ ' xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"',
+ ' xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"',
+ ' xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"',
+]
+
+def xmlToText(xElem):
+ """Get the text content of an XML element.
+ """
+ rTxt = etree.tostring(xElem, encoding="utf-8", xml_declaration=False).decode()
+ for nSpace in XML_NS:
+ rTxt = rTxt.replace(nSpace, "")
+ return rTxt
+
@pytest.mark.core
def testCoreToOdt_Convert(tmpConf, dummyGUI):
"""Test the converter of the ToHtml class.
@@ -46,6 +63,22 @@ def testCoreToOdt_Convert(tmpConf, dummyGUI):
theDoc.initDocument()
theDoc.doConvert()
theDoc.closeDocument()
- assert theDoc.theResult == ""
+ assert xmlToText(theDoc._xText) == (
+ ''
+ 'Title'
+ ''
+ )
+
+ # Header 1
+ theDoc.theText = "## Chapter Title\n"
+ theDoc.tokenizeText()
+ theDoc.initDocument()
+ theDoc.doConvert()
+ theDoc.closeDocument()
+ assert xmlToText(theDoc._xText) == (
+ ''
+ 'Chapter Title'
+ ''
+ )
# END Test testCoreToOdt_Convert