Replace lxml with standard xml for project files

This commit is contained in:
Veronica Berglyd Olsen
2023-05-29 17:00:52 +02:00
parent 03a19a882b
commit 59931c804c
5 changed files with 104 additions and 55 deletions
+45
View File
@@ -27,6 +27,7 @@ import json
import uuid import uuid
import hashlib import hashlib
import logging import logging
import xml.etree.ElementTree as ET
from pathlib import Path from pathlib import Path
from datetime import datetime from datetime import datetime
@@ -562,3 +563,47 @@ class NWConfigParser(ConfigParser):
return result return result
# END Class NWConfigParser # END Class NWConfigParser
# =============================================================================================== #
# Third Party Code
# =============================================================================================== #
def xmlIndent(tree, space=" ", level=0):
"""The XML indent function from CPython, that was only added in Python 3.9.
It is included here to support older versions of Python.
https://github.com/python/cpython/blob/main/Lib/xml/etree/ElementTree.py
"""
if isinstance(tree, ET.ElementTree):
tree = tree.getroot()
if level < 0:
raise ValueError(f"Initial indentation level must be >= 0, got {level}")
if not len(tree):
return
# Reduce the memory consumption by reusing indentation strings.
indentations = ["\n" + level * space]
def _indent_children(elem, level):
# Start a new indentation level for the first child.
child_level = level + 1
try:
child_indentation = indentations[child_level]
except IndexError:
child_indentation = indentations[level] + space
indentations.append(child_indentation)
if not elem.text or not elem.text.strip():
elem.text = child_indentation
for child in elem:
if len(child):
_indent_children(child, child_level)
if not child.tail or not child.tail.strip():
child.tail = child_indentation
# Dedent after the last child by overwriting the previous indentation.
if not child.tail.strip(): # type: ignore
child.tail = indentations[level] # type: ignore
_indent_children(tree, 0)
-1
View File
@@ -196,7 +196,6 @@ class Config:
# Check Python Version # Check Python Version
self.verPyString = sys.version.split()[0] self.verPyString = sys.version.split()[0]
self.verPyHexVal = sys.hexversion
# Check OS Type # Check OS Type
self.osType = sys.platform self.osType = sys.platform
+23 -19
View File
@@ -25,17 +25,18 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
""" """
import sys
import logging import logging
import xml.etree.ElementTree as ET
from enum import Enum from enum import Enum
from lxml import etree
from time import time from time import time
from pathlib import Path from pathlib import Path
from novelwriter import __version__, __hexversion__ from novelwriter import __version__, __hexversion__
from novelwriter.common import ( from novelwriter.common import (
checkBool, checkInt, checkString, checkStringNone, formatTimeStamp, checkBool, checkInt, checkString, checkStringNone, formatTimeStamp,
hexToInt, simplified, yesNo hexToInt, simplified, xmlIndent, yesNo
) )
from novelwriter.constants import nwFiles from novelwriter.constants import nwFiles
@@ -163,7 +164,7 @@ class ProjectXMLReader:
logger.debug("Reading project XML") logger.debug("Reading project XML")
try: try:
xml = etree.parse(str(self._path)) xml = ET.parse(str(self._path))
self._state = XMLReadState.NO_ERROR self._state = XMLReadState.NO_ERROR
except Exception as exc: except Exception as exc:
@@ -174,7 +175,7 @@ class ProjectXMLReader:
backFile = self._path.with_suffix(".bak") backFile = self._path.with_suffix(".bak")
if backFile.is_file(): if backFile.is_file():
try: try:
xml = etree.parse(str(backFile)) xml = ET.parse(str(backFile))
self._state = XMLReadState.PARSED_BACKUP self._state = XMLReadState.PARSED_BACKUP
logger.info("Backup project file parsed") logger.info("Backup project file parsed")
except Exception as exc: except Exception as exc:
@@ -500,7 +501,7 @@ class ProjectXMLWriter:
tStart = time() tStart = time()
logger.debug("Writing project XML") logger.debug("Writing project XML")
xRoot = etree.Element("novelWriterXML", attrib={ xRoot = ET.Element("novelWriterXML", attrib={
"appVersion": str(__version__), "appVersion": str(__version__),
"hexVersion": str(__hexversion__), "hexVersion": str(__hexversion__),
"fileVersion": FILE_VERSION, "fileVersion": FILE_VERSION,
@@ -515,13 +516,13 @@ class ProjectXMLWriter:
"editTime": str(editTime), "editTime": str(editTime),
} }
xProject = etree.SubElement(xRoot, "project", attrib=projAttr) xProject = ET.SubElement(xRoot, "project", attrib=projAttr)
self._packSingleValue(xProject, "name", projData.name) self._packSingleValue(xProject, "name", projData.name)
self._packSingleValue(xProject, "title", projData.title) self._packSingleValue(xProject, "title", projData.title)
self._packSingleValue(xProject, "author", projData.author) self._packSingleValue(xProject, "author", projData.author)
# Save Project Settings # Save Project Settings
xSettings = etree.SubElement(xRoot, "settings") xSettings = ET.SubElement(xRoot, "settings")
self._packSingleValue(xSettings, "doBackup", yesNo(projData.doBackup)) self._packSingleValue(xSettings, "doBackup", yesNo(projData.doBackup))
self._packSingleValue(xSettings, "language", projData.language) self._packSingleValue(xSettings, "language", projData.language)
self._packSingleValue(xSettings, "spellChecking", projData.spellLang, attrib={ self._packSingleValue(xSettings, "spellChecking", projData.spellLang, attrib={
@@ -532,11 +533,11 @@ class ProjectXMLWriter:
self._packDictKeyValue(xSettings, "titleFormat", projData.titleFormat) self._packDictKeyValue(xSettings, "titleFormat", projData.titleFormat)
# Save Status/Importance # Save Status/Importance
xStatus = etree.SubElement(xSettings, "status") xStatus = ET.SubElement(xSettings, "status")
for label, attrib in projData.itemStatus.pack(): for label, attrib in projData.itemStatus.pack():
self._packSingleValue(xStatus, "entry", label, attrib=attrib) self._packSingleValue(xStatus, "entry", label, attrib=attrib)
xImport = etree.SubElement(xSettings, "importance") xImport = ET.SubElement(xSettings, "importance")
for label, attrib in projData.itemImport.pack(): for label, attrib in projData.itemImport.pack():
self._packSingleValue(xImport, "entry", label, attrib=attrib) self._packSingleValue(xImport, "entry", label, attrib=attrib)
@@ -547,11 +548,11 @@ class ProjectXMLWriter:
"notesWords": str(projData.currCounts[1]), "notesWords": str(projData.currCounts[1]),
} }
xContent = etree.SubElement(xRoot, "content", attrib=contAttr) xContent = ET.SubElement(xRoot, "content", attrib=contAttr)
for item in projContent: for item in projContent:
xItem = etree.SubElement(xContent, "item", attrib=item.get("itemAttr", {})) xItem = ET.SubElement(xContent, "item", attrib=item.get("itemAttr", {}))
etree.SubElement(xItem, "meta", attrib=item.get("metaAttr", {})) ET.SubElement(xItem, "meta", attrib=item.get("metaAttr", {}))
xName = etree.SubElement(xItem, "name", attrib=item.get("nameAttr", {})) xName = ET.SubElement(xItem, "name", attrib=item.get("nameAttr", {}))
xName.text = item["name"] xName.text = item["name"]
# Write the XML tree to file # Write the XML tree to file
@@ -559,9 +560,12 @@ class ProjectXMLWriter:
tempFile = saveFile.with_suffix(".tmp") tempFile = saveFile.with_suffix(".tmp")
backFile = saveFile.with_suffix(".bak") backFile = saveFile.with_suffix(".bak")
try: try:
tempFile.write_bytes(etree.tostring( xml = ET.ElementTree(xRoot)
xRoot, pretty_print=True, encoding="utf-8", xml_declaration=True if sys.hexversion < 0x030900f0:
)) xmlIndent(xml, space=" ")
else:
ET.indent(xml, space=" ")
xml.write(tempFile, encoding="utf-8", xml_declaration=True)
except Exception as exc: except Exception as exc:
self._error = exc self._error = exc
return False return False
@@ -587,17 +591,17 @@ class ProjectXMLWriter:
def _packSingleValue(self, xParent, name, value, attrib=None): def _packSingleValue(self, xParent, name, value, attrib=None):
"""Pack a single value into an XML element. """Pack a single value into an XML element.
""" """
xItem = etree.SubElement(xParent, name, attrib=attrib) xItem = ET.SubElement(xParent, name, attrib=attrib or {})
xItem.text = str(value) or "" xItem.text = str(value) or ""
return return
def _packDictKeyValue(self, xParent, name, data): def _packDictKeyValue(self, xParent, name, data):
"""Pack the entries of a dictionary into an XML element. """Pack the entries of a dictionary into an XML element.
""" """
xItem = etree.SubElement(xParent, name) xItem = ET.SubElement(xParent, name)
for key, value in data.items(): for key, value in data.items():
if len(key) > 0: if len(key) > 0:
xEntry = etree.SubElement(xItem, "entry", attrib={"key": key}) xEntry = ET.SubElement(xItem, "entry", attrib={"key": key})
xEntry.text = str(value) or "" xEntry.text = str(value) or ""
return return
+5 -4
View File
@@ -23,6 +23,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
""" """
import sys
import logging import logging
from enum import Enum from enum import Enum
@@ -31,10 +32,10 @@ from pathlib import Path
from datetime import datetime from datetime import datetime
from PyQt5.QtCore import Qt, QTimer, QThreadPool, pyqtSlot from PyQt5.QtCore import Qt, QTimer, QThreadPool, pyqtSlot
from PyQt5.QtGui import QIcon, QKeySequence, QCursor from PyQt5.QtGui import QCursor, QIcon, QKeySequence
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
qApp, QMainWindow, QVBoxLayout, QWidget, QSplitter, QFileDialog, QShortcut, qApp, QDialog, QFileDialog, QMainWindow, QMessageBox, QShortcut, QSplitter,
QMessageBox, QDialog, QStackedWidget QStackedWidget, QVBoxLayout, QWidget
) )
from novelwriter import CONFIG, __hexversion__ from novelwriter import CONFIG, __hexversion__
@@ -88,7 +89,7 @@ class GuiMain(QMainWindow):
logger.info("Host: %s", CONFIG.hostName) logger.info("Host: %s", CONFIG.hostName)
logger.info("Qt5: %s (0x%06x)", CONFIG.verQtString, CONFIG.verQtValue) logger.info("Qt5: %s (0x%06x)", CONFIG.verQtString, CONFIG.verQtValue)
logger.info("PyQt5: %s (0x%06x)", CONFIG.verPyQtString, CONFIG.verPyQtValue) logger.info("PyQt5: %s (0x%06x)", CONFIG.verPyQtString, CONFIG.verPyQtValue)
logger.info("Python: %s (0x%08x)", CONFIG.verPyString, CONFIG.verPyHexVal) logger.info("Python: %s (0x%08x)", CONFIG.verPyString, sys.hexversion)
logger.info("GUI Language: %s", CONFIG.guiLocale) logger.info("GUI Language: %s", CONFIG.guiLocale)
# Core Classes # Core Classes
+30 -30
View File
@@ -1,6 +1,6 @@
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="2.0.7" hexVersion="0x020007f0" fileVersion="1.5" timeStamp="2023-04-15 20:52:06"> <novelWriterXML appVersion="2.0.7" hexVersion="0x020007f0" fileVersion="1.5" timeStamp="2023-05-29 16:50:14">
<project id="e2be99af-f9bf-4403-857a-c3d1ac25abea" saveCount="1475" autoCount="237" editTime="74579"> <project id="e2be99af-f9bf-4403-857a-c3d1ac25abea" saveCount="1483" autoCount="237" editTime="74603">
<name>Sample Project</name> <name>Sample Project</name>
<title>Sample Project</title> <title>Sample Project</title>
<author>Jane Smith</author> <author>Jane Smith</author>
@@ -25,7 +25,7 @@
<entry key="chapter">Chapter %chw%: %title%</entry> <entry key="chapter">Chapter %chw%: %title%</entry>
<entry key="unnumbered">%title%</entry> <entry key="unnumbered">%title%</entry>
<entry key="scene">Scene %ch%.%sc%: %title%</entry> <entry key="scene">Scene %ch%.%sc%: %title%</entry>
<entry key="section"></entry> <entry key="section" />
</titleFormat> </titleFormat>
<status> <status>
<entry key="sf12341" count="4" red="100" green="100" blue="100">New</entry> <entry key="sf12341" count="4" red="100" green="100" blue="100">New</entry>
@@ -45,111 +45,111 @@
</settings> </settings>
<content items="27" novelWords="954" notesWords="409"> <content items="27" novelWords="954" notesWords="409">
<item handle="7031beac91f75" parent="None" root="7031beac91f75" order="0" type="ROOT" class="NOVEL"> <item handle="7031beac91f75" parent="None" root="7031beac91f75" order="0" type="ROOT" class="NOVEL">
<meta expanded="yes"/> <meta expanded="yes" />
<name status="sc24b8f" import="ia857f0">Novel</name> <name status="sc24b8f" import="ia857f0">Novel</name>
</item> </item>
<item handle="53b69b83cdafc" parent="7031beac91f75" root="7031beac91f75" order="0" type="FILE" class="NOVEL" layout="DOCUMENT"> <item handle="53b69b83cdafc" parent="7031beac91f75" root="7031beac91f75" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="no" heading="H1" charCount="95" wordCount="19" paraCount="2" cursorPos="31"/> <meta expanded="no" heading="H1" charCount="95" wordCount="19" paraCount="2" cursorPos="31" />
<name status="sc24b8f" import="ia857f0" active="yes">Title Page</name> <name status="sc24b8f" import="ia857f0" active="yes">Title Page</name>
</item> </item>
<item handle="974e400180a99" parent="7031beac91f75" root="7031beac91f75" order="1" type="FILE" class="NOVEL" layout="DOCUMENT"> <item handle="974e400180a99" parent="7031beac91f75" root="7031beac91f75" order="1" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="no" heading="H0" charCount="251" wordCount="50" paraCount="2" cursorPos="277"/> <meta expanded="no" heading="H0" charCount="251" wordCount="50" paraCount="2" cursorPos="277" />
<name status="sf12341" import="ia857f0" active="yes">Page</name> <name status="sf12341" import="ia857f0" active="yes">Page</name>
</item> </item>
<item handle="edca4be2fcaf8" parent="7031beac91f75" root="7031beac91f75" order="2" type="FILE" class="NOVEL" layout="DOCUMENT"> <item handle="edca4be2fcaf8" parent="7031beac91f75" root="7031beac91f75" order="2" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="no" heading="H1" charCount="26" wordCount="6" paraCount="1" cursorPos="36"/> <meta expanded="no" heading="H1" charCount="26" wordCount="6" paraCount="1" cursorPos="36" />
<name status="s90e6c9" import="ia857f0" active="yes">Part One</name> <name status="s90e6c9" import="ia857f0" active="yes">Part One</name>
</item> </item>
<item handle="6a2d6d5f4f401" parent="7031beac91f75" root="7031beac91f75" order="3" type="FILE" class="NOVEL" layout="DOCUMENT"> <item handle="6a2d6d5f4f401" parent="7031beac91f75" root="7031beac91f75" order="3" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="yes" heading="H2" charCount="95" wordCount="18" paraCount="1" cursorPos="291"/> <meta expanded="yes" heading="H2" charCount="95" wordCount="18" paraCount="1" cursorPos="291" />
<name status="sf24ce6" import="ia857f0" active="yes">Chapter One</name> <name status="sf24ce6" import="ia857f0" active="yes">Chapter One</name>
</item> </item>
<item handle="636b6aa9b697b" parent="6a2d6d5f4f401" root="7031beac91f75" order="0" type="FILE" class="NOVEL" layout="DOCUMENT"> <item handle="636b6aa9b697b" parent="6a2d6d5f4f401" root="7031beac91f75" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="no" heading="H3" charCount="2687" wordCount="479" paraCount="14" cursorPos="67"/> <meta expanded="no" heading="H3" charCount="2687" wordCount="479" paraCount="14" cursorPos="1090" />
<name status="s90e6c9" import="ia857f0" active="yes">Making a Scene</name> <name status="s90e6c9" import="ia857f0" active="yes">Making a Scene</name>
</item> </item>
<item handle="bc0cbd2a407f3" parent="6a2d6d5f4f401" root="7031beac91f75" order="1" type="FILE" class="NOVEL" layout="DOCUMENT"> <item handle="bc0cbd2a407f3" parent="6a2d6d5f4f401" root="7031beac91f75" order="1" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="no" heading="H3" charCount="548" wordCount="108" paraCount="3" cursorPos="465"/> <meta expanded="no" heading="H3" charCount="548" wordCount="108" paraCount="3" cursorPos="465" />
<name status="s90e6c9" import="ia857f0" active="yes">Another Scene</name> <name status="s90e6c9" import="ia857f0" active="yes">Another Scene</name>
</item> </item>
<item handle="ba8a28a246524" parent="7031beac91f75" root="7031beac91f75" order="4" type="FILE" class="NOVEL" layout="DOCUMENT"> <item handle="ba8a28a246524" parent="7031beac91f75" root="7031beac91f75" order="4" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="no" heading="H2" charCount="617" wordCount="101" paraCount="3" cursorPos="310"/> <meta expanded="no" heading="H2" charCount="617" wordCount="101" paraCount="3" cursorPos="310" />
<name status="s78ea90" import="ia857f0" active="yes">Interlude</name> <name status="s78ea90" import="ia857f0" active="yes">Interlude</name>
</item> </item>
<item handle="96b68994dfa3d" parent="7031beac91f75" root="7031beac91f75" order="5" type="FILE" class="NOVEL" layout="NOTE"> <item handle="96b68994dfa3d" parent="7031beac91f75" root="7031beac91f75" order="5" type="FILE" class="NOVEL" layout="NOTE">
<meta expanded="no" heading="H1" charCount="1909" wordCount="346" paraCount="7" cursorPos="0"/> <meta expanded="no" heading="H1" charCount="1909" wordCount="346" paraCount="7" cursorPos="0" />
<name status="sf24ce6" import="ia857f0" active="no">A Note on Structure</name> <name status="sf24ce6" import="ia857f0" active="no">A Note on Structure</name>
</item> </item>
<item handle="88706ddc78b1b" parent="7031beac91f75" root="7031beac91f75" order="6" type="FILE" class="NOVEL" layout="DOCUMENT"> <item handle="88706ddc78b1b" parent="7031beac91f75" root="7031beac91f75" order="6" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="yes" heading="H2" charCount="139" wordCount="28" paraCount="1" cursorPos="188"/> <meta expanded="yes" heading="H2" charCount="139" wordCount="28" paraCount="1" cursorPos="188" />
<name status="s90e6c9" import="ia857f0" active="yes">Chapter Two</name> <name status="s90e6c9" import="ia857f0" active="yes">Chapter Two</name>
</item> </item>
<item handle="ae7339df26ded" parent="88706ddc78b1b" root="7031beac91f75" order="0" type="FILE" class="NOVEL" layout="DOCUMENT"> <item handle="ae7339df26ded" parent="88706ddc78b1b" root="7031beac91f75" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="no" heading="H3" charCount="189" wordCount="37" paraCount="1" cursorPos="0"/> <meta expanded="no" heading="H3" charCount="189" wordCount="37" paraCount="1" cursorPos="0" />
<name status="s90e6c9" import="ia857f0" active="yes">We Found John!</name> <name status="s90e6c9" import="ia857f0" active="yes">We Found John!</name>
</item> </item>
<item handle="e5e47ebf63b1c" parent="None" root="e5e47ebf63b1c" order="1" type="ROOT" class="NOVEL"> <item handle="e5e47ebf63b1c" parent="None" root="e5e47ebf63b1c" order="1" type="ROOT" class="NOVEL">
<meta expanded="yes"/> <meta expanded="yes" />
<name status="sf12341" import="ia857f0">Sequel</name> <name status="sf12341" import="ia857f0">Sequel</name>
</item> </item>
<item handle="bacb7059e3083" parent="e5e47ebf63b1c" root="e5e47ebf63b1c" order="0" type="FILE" class="NOVEL" layout="DOCUMENT"> <item handle="bacb7059e3083" parent="e5e47ebf63b1c" root="e5e47ebf63b1c" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="no" heading="H1" charCount="27" wordCount="5" paraCount="1" cursorPos="100"/> <meta expanded="no" heading="H1" charCount="27" wordCount="5" paraCount="1" cursorPos="100" />
<name status="sc24b8f" import="ia857f0" active="yes">Title Page</name> <name status="sc24b8f" import="ia857f0" active="yes">Title Page</name>
</item> </item>
<item handle="a520879ca0b45" parent="e5e47ebf63b1c" root="e5e47ebf63b1c" order="1" type="FILE" class="NOVEL" layout="DOCUMENT"> <item handle="a520879ca0b45" parent="e5e47ebf63b1c" root="e5e47ebf63b1c" order="1" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="no" heading="H2" charCount="299" wordCount="55" paraCount="2" cursorPos="104"/> <meta expanded="no" heading="H2" charCount="299" wordCount="55" paraCount="2" cursorPos="104" />
<name status="s90e6c9" import="ia857f0" active="yes">Chapter One</name> <name status="s90e6c9" import="ia857f0" active="yes">Chapter One</name>
</item> </item>
<item handle="f6622b4617424" parent="None" root="f6622b4617424" order="2" type="ROOT" class="CHARACTER"> <item handle="f6622b4617424" parent="None" root="f6622b4617424" order="2" type="ROOT" class="CHARACTER">
<meta expanded="yes"/> <meta expanded="yes" />
<name status="sf12341" import="ia857f0">Characters</name> <name status="sf12341" import="ia857f0">Characters</name>
</item> </item>
<item handle="f7e2d9f330615" parent="f6622b4617424" root="f6622b4617424" order="0" type="FOLDER" class="CHARACTER"> <item handle="f7e2d9f330615" parent="f6622b4617424" root="f6622b4617424" order="0" type="FOLDER" class="CHARACTER">
<meta expanded="yes"/> <meta expanded="yes" />
<name status="sf12341" import="ia857f0">Main Characters</name> <name status="sf12341" import="ia857f0">Main Characters</name>
</item> </item>
<item handle="14298de4d9524" parent="f7e2d9f330615" root="f6622b4617424" order="0" type="FILE" class="CHARACTER" layout="NOTE"> <item handle="14298de4d9524" parent="f7e2d9f330615" root="f6622b4617424" order="0" type="FILE" class="CHARACTER" layout="NOTE">
<meta expanded="no" heading="H1" charCount="49" wordCount="9" paraCount="1" cursorPos="24"/> <meta expanded="no" heading="H1" charCount="49" wordCount="9" paraCount="1" cursorPos="24" />
<name status="sf12341" import="icfb3a5" active="yes">John Smith</name> <name status="sf12341" import="icfb3a5" active="yes">John Smith</name>
</item> </item>
<item handle="bb2c23b3c42cc" parent="f7e2d9f330615" root="f6622b4617424" order="1" type="FILE" class="CHARACTER" layout="NOTE"> <item handle="bb2c23b3c42cc" parent="f7e2d9f330615" root="f6622b4617424" order="1" type="FILE" class="CHARACTER" layout="NOTE">
<meta expanded="no" heading="H1" charCount="55" wordCount="9" paraCount="1" cursorPos="25"/> <meta expanded="no" heading="H1" charCount="55" wordCount="9" paraCount="1" cursorPos="25" />
<name status="sf12341" import="i2d7a54" active="yes">Jane Smith</name> <name status="sf12341" import="i2d7a54" active="yes">Jane Smith</name>
</item> </item>
<item handle="15c4492bd5107" parent="None" root="15c4492bd5107" order="3" type="ROOT" class="WORLD"> <item handle="15c4492bd5107" parent="None" root="15c4492bd5107" order="3" type="ROOT" class="WORLD">
<meta expanded="yes"/> <meta expanded="yes" />
<name status="sf12341" import="ia857f0">Locations</name> <name status="sf12341" import="ia857f0">Locations</name>
</item> </item>
<item handle="b3e74dbc1f584" parent="15c4492bd5107" root="15c4492bd5107" order="0" type="FILE" class="WORLD" layout="NOTE"> <item handle="b3e74dbc1f584" parent="15c4492bd5107" root="15c4492bd5107" order="0" type="FILE" class="WORLD" layout="NOTE">
<meta expanded="no" heading="H1" charCount="76" wordCount="15" paraCount="1" cursorPos="20"/> <meta expanded="no" heading="H1" charCount="76" wordCount="15" paraCount="1" cursorPos="20" />
<name status="sf12341" import="i56be10" active="yes">Earth</name> <name status="sf12341" import="i56be10" active="yes">Earth</name>
</item> </item>
<item handle="f1471bef9f2ae" parent="15c4492bd5107" root="15c4492bd5107" order="1" type="FILE" class="WORLD" layout="NOTE"> <item handle="f1471bef9f2ae" parent="15c4492bd5107" root="15c4492bd5107" order="1" type="FILE" class="WORLD" layout="NOTE">
<meta expanded="no" heading="H1" charCount="115" wordCount="24" paraCount="1" cursorPos="133"/> <meta expanded="no" heading="H1" charCount="115" wordCount="24" paraCount="1" cursorPos="133" />
<name status="sf12341" import="icfb3a5" active="yes">Space</name> <name status="sf12341" import="icfb3a5" active="yes">Space</name>
</item> </item>
<item handle="5eaea4e8cdee8" parent="15c4492bd5107" root="15c4492bd5107" order="2" type="FILE" class="WORLD" layout="NOTE"> <item handle="5eaea4e8cdee8" parent="15c4492bd5107" root="15c4492bd5107" order="2" type="FILE" class="WORLD" layout="NOTE">
<meta expanded="no" heading="H1" charCount="28" wordCount="6" paraCount="1" cursorPos="45"/> <meta expanded="no" heading="H1" charCount="28" wordCount="6" paraCount="1" cursorPos="45" />
<name status="sf12341" import="i2d7a54" active="yes">Mars</name> <name status="sf12341" import="i2d7a54" active="yes">Mars</name>
</item> </item>
<item handle="6827118336ac1" parent="None" root="6827118336ac1" order="4" type="ROOT" class="ARCHIVE"> <item handle="6827118336ac1" parent="None" root="6827118336ac1" order="4" type="ROOT" class="ARCHIVE">
<meta expanded="yes"/> <meta expanded="yes" />
<name status="sf12341" import="ia857f0">Archive</name> <name status="sf12341" import="ia857f0">Archive</name>
</item> </item>
<item handle="ae9bf3c3ea159" parent="6827118336ac1" root="6827118336ac1" order="0" type="FOLDER" class="ARCHIVE"> <item handle="ae9bf3c3ea159" parent="6827118336ac1" root="6827118336ac1" order="0" type="FOLDER" class="ARCHIVE">
<meta expanded="yes"/> <meta expanded="yes" />
<name status="sf12341" import="ia857f0">Scenes</name> <name status="sf12341" import="ia857f0">Scenes</name>
</item> </item>
<item handle="8a5deb88c0e97" parent="ae9bf3c3ea159" root="6827118336ac1" order="0" type="FILE" class="ARCHIVE" layout="DOCUMENT"> <item handle="8a5deb88c0e97" parent="ae9bf3c3ea159" root="6827118336ac1" order="0" type="FILE" class="ARCHIVE" layout="DOCUMENT">
<meta expanded="no" heading="H3" charCount="232" wordCount="42" paraCount="1" cursorPos="239"/> <meta expanded="no" heading="H3" charCount="232" wordCount="42" paraCount="1" cursorPos="239" />
<name status="s90e6c9" import="ia857f0" active="yes">Old File</name> <name status="s90e6c9" import="ia857f0" active="yes">Old File</name>
</item> </item>
<item handle="98acd8c76c93a" parent="None" root="98acd8c76c93a" order="5" type="ROOT" class="TRASH"> <item handle="98acd8c76c93a" parent="None" root="98acd8c76c93a" order="5" type="ROOT" class="TRASH">
<meta expanded="yes"/> <meta expanded="yes" />
<name status="sf12341" import="ia857f0">Trash</name> <name status="sf12341" import="ia857f0">Trash</name>
</item> </item>
<item handle="b8136a5a774a0" parent="98acd8c76c93a" root="98acd8c76c93a" order="0" type="FILE" class="TRASH" layout="DOCUMENT"> <item handle="b8136a5a774a0" parent="98acd8c76c93a" root="98acd8c76c93a" order="0" type="FILE" class="TRASH" layout="DOCUMENT">
<meta expanded="no" heading="H3" charCount="30" wordCount="6" paraCount="1" cursorPos="36"/> <meta expanded="no" heading="H3" charCount="30" wordCount="6" paraCount="1" cursorPos="36" />
<name status="sf12341" import="ia857f0" active="yes">Delete Me!</name> <name status="sf12341" import="ia857f0" active="yes">Delete Me!</name>
</item> </item>
</content> </content>