850 lines
25 KiB
Python
850 lines
25 KiB
Python
![]() |
"""
|
||
|
The xml_simple_reader.py script is an xml parser that can parse a line separated xml text.
|
||
|
|
||
|
This xml parser will read a line seperated xml text and produce a tree of the xml with a document element. Each element can have an attribute table, childNodes, a class name, parentNode, text and a link to the document element.
|
||
|
|
||
|
This example gets an xml tree for the xml file boolean.xml. This example is run in a terminal in the folder which contains boolean.xml and xml_simple_reader.py.
|
||
|
|
||
|
|
||
|
> python
|
||
|
Python 2.5.1 (r251:54863, Sep 22 2007, 01:43:31)
|
||
|
[GCC 4.2.1 (SUSE Linux)] on linux2
|
||
|
Type "help", "copyright", "credits" or "license" for more information.
|
||
|
>>> fileName = 'boolean.xml'
|
||
|
>>> file = open(fileName, 'r')
|
||
|
>>> xmlText = file.read()
|
||
|
>>> file.close()
|
||
|
>>> from xml_simple_reader import DocumentNode
|
||
|
>>> xmlParser = DocumentNode(fileName, xmlText)
|
||
|
>>> print(xmlParser)
|
||
|
?xml, {'version': '1.0'}
|
||
|
ArtOfIllusion, {'xmlns:bf': '//babelfiche/codec', 'version': '2.0', 'fileversion': '3'}
|
||
|
Scene, {'bf:id': 'theScene'}
|
||
|
materials, {'bf:elem-type': 'java.lang.Object', 'bf:list': 'collection', 'bf:id': '1', 'bf:type': 'java.util.Vector'}
|
||
|
..
|
||
|
many more lines of the xml tree
|
||
|
..
|
||
|
|
||
|
"""
|
||
|
|
||
|
|
||
|
from __future__ import absolute_import
|
||
|
#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module.
|
||
|
import __init__
|
||
|
|
||
|
from fabmetheus_utilities.geometry.geometry_utilities import evaluate
|
||
|
from fabmetheus_utilities.geometry.geometry_utilities import matrix
|
||
|
from fabmetheus_utilities import archive
|
||
|
from fabmetheus_utilities import euclidean
|
||
|
from fabmetheus_utilities import xml_simple_writer
|
||
|
import cStringIO
|
||
|
|
||
|
|
||
|
__author__ = 'Enrique Perez (perez_enrique@yahoo.com)'
|
||
|
__credits__ = 'Nophead <http://hydraraptor.blogspot.com/>\nArt of Illusion <http://www.artofillusion.org/>'
|
||
|
__date__ = '$Date: 2008/21/04 $'
|
||
|
__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
|
||
|
|
||
|
|
||
|
globalGetAccessibleAttributeSet = set('getPaths getPreviousVertex getPreviousElementNode getVertexes parentNode'.split())
|
||
|
|
||
|
|
||
|
def createAppendByText(parentNode, xmlText):
|
||
|
'Create and append the child nodes from the xmlText.'
|
||
|
monad = OpenMonad(parentNode)
|
||
|
for character in xmlText:
|
||
|
monad = monad.getNextMonad(character)
|
||
|
|
||
|
def createAppendByTextb(parentNode, xmlText):
|
||
|
'Create and append the child nodes from the xmlText.'
|
||
|
monad = OpenMonad(parentNode)
|
||
|
for character in xmlText:
|
||
|
monad = monad.getNextMonad(character)
|
||
|
|
||
|
def getChildElementsByLocalName(childNodes, localName):
|
||
|
'Get the childNodes which have the given local name.'
|
||
|
childElementsByLocalName = []
|
||
|
for childNode in childNodes:
|
||
|
if localName.lower() == childNode.getNodeName():
|
||
|
childElementsByLocalName.append(childNode)
|
||
|
return childElementsByLocalName
|
||
|
|
||
|
def getDocumentNode(fileName):
|
||
|
'Get the document from the file name.'
|
||
|
xmlText = getFileText('test.xml')
|
||
|
return DocumentNode(fileName, xmlText)
|
||
|
|
||
|
def getElementsByLocalName(childNodes, localName):
|
||
|
'Get the descendents which have the given local name.'
|
||
|
elementsByLocalName = getChildElementsByLocalName(childNodes, localName)
|
||
|
for childNode in childNodes:
|
||
|
if childNode.getNodeType() == 1:
|
||
|
elementsByLocalName += childNode.getElementsByLocalName(localName)
|
||
|
return elementsByLocalName
|
||
|
|
||
|
def getFileText(fileName, printWarning=True, readMode='r'):
|
||
|
'Get the entire text of a file.'
|
||
|
try:
|
||
|
file = open(fileName, readMode)
|
||
|
fileText = file.read()
|
||
|
file.close()
|
||
|
return fileText
|
||
|
except IOError:
|
||
|
if printWarning:
|
||
|
print('The file ' + fileName + ' does not exist.')
|
||
|
return ''
|
||
|
|
||
|
|
||
|
class CDATASectionMonad:
|
||
|
'A monad to handle a CDATASection node.'
|
||
|
def __init__(self, input, parentNode):
|
||
|
'Initialize.'
|
||
|
self.input = input
|
||
|
self.parentNode = parentNode
|
||
|
|
||
|
def getNextMonad(self, character):
|
||
|
'Get the next monad.'
|
||
|
self.input.write(character)
|
||
|
if character == '>':
|
||
|
inputString = self.input.getvalue()
|
||
|
if inputString.endswith(']]>'):
|
||
|
textContent = '<%s\n' % inputString
|
||
|
self.parentNode.childNodes.append(CDATASectionNode(self.parentNode, textContent))
|
||
|
return OpenMonad(self.parentNode)
|
||
|
return self
|
||
|
|
||
|
|
||
|
class CDATASectionNode:
|
||
|
'A CDATASection node.'
|
||
|
def __init__(self, parentNode, textContent=''):
|
||
|
'Initialize.'
|
||
|
self.parentNode = parentNode
|
||
|
self.textContent = textContent
|
||
|
|
||
|
def __repr__(self):
|
||
|
'Get the string representation of this CDATASection node.'
|
||
|
return self.textContent
|
||
|
|
||
|
def addToIdentifierDictionaries(self):
|
||
|
'Add the element to the owner document identifier dictionaries.'
|
||
|
pass
|
||
|
|
||
|
def addXML(self, depth, output):
|
||
|
'Add xml for this CDATASection node.'
|
||
|
output.write(self.textContent)
|
||
|
|
||
|
def appendSelfToParent(self):
|
||
|
'Append self to the parentNode.'
|
||
|
self.parentNode.appendChild(self)
|
||
|
|
||
|
def copyXMLChildNodes(self, idSuffix, parentNode):
|
||
|
'Copy the xml childNodes.'
|
||
|
pass
|
||
|
|
||
|
def getAttributes(self):
|
||
|
'Get the attributes.'
|
||
|
return {}
|
||
|
|
||
|
def getChildNodes(self):
|
||
|
'Get the empty set.'
|
||
|
return []
|
||
|
|
||
|
def getCopy(self, idSuffix, parentNode):
|
||
|
'Copy the xml element, set its dictionary and add it to the parentNode.'
|
||
|
copy = self.getCopyShallow()
|
||
|
copy.parentNode = parentNode
|
||
|
copy.appendSelfToParent()
|
||
|
return copy
|
||
|
|
||
|
def getCopyShallow(self, attributes=None):
|
||
|
'Copy the node and set its parentNode.'
|
||
|
return CDATASectionNode(self.parentNode, self.textContent)
|
||
|
|
||
|
def getNodeName(self):
|
||
|
'Get the node name.'
|
||
|
return '#cdata-section'
|
||
|
|
||
|
def getNodeType(self):
|
||
|
'Get the node type.'
|
||
|
return 4
|
||
|
|
||
|
def getOwnerDocument(self):
|
||
|
'Get the owner document.'
|
||
|
return self.parentNode.getOwnerDocument()
|
||
|
|
||
|
def getTextContent(self):
|
||
|
'Get the text content.'
|
||
|
return self.textContent
|
||
|
|
||
|
def removeChildNodesFromIDNameParent(self):
|
||
|
'Remove the childNodes from the id and name dictionaries and the childNodes.'
|
||
|
pass
|
||
|
|
||
|
def removeFromIDNameParent(self):
|
||
|
'Remove this from the id and name dictionaries and the childNodes of the parentNode.'
|
||
|
if self.parentNode != None:
|
||
|
self.parentNode.childNodes.remove(self)
|
||
|
|
||
|
def setParentAddToChildNodes(self, parentNode):
|
||
|
'Set the parentNode and add this to its childNodes.'
|
||
|
self.parentNode = parentNode
|
||
|
if self.parentNode != None:
|
||
|
self.parentNode.childNodes.append(self)
|
||
|
|
||
|
attributes = property(getAttributes)
|
||
|
childNodes = property(getChildNodes)
|
||
|
nodeName = property(getNodeName)
|
||
|
nodeType = property(getNodeType)
|
||
|
ownerDocument = property(getOwnerDocument)
|
||
|
|
||
|
|
||
|
class CommentMonad(CDATASectionMonad):
|
||
|
'A monad to handle a comment node.'
|
||
|
def getNextMonad(self, character):
|
||
|
'Get the next monad.'
|
||
|
self.input.write(character)
|
||
|
if character == '>':
|
||
|
inputString = self.input.getvalue()
|
||
|
if inputString.endswith('-->'):
|
||
|
textContent = '<%s\n' % inputString
|
||
|
self.parentNode.childNodes.append(CommentNode(self.parentNode, textContent))
|
||
|
return OpenMonad(self.parentNode)
|
||
|
return self
|
||
|
|
||
|
|
||
|
class CommentNode(CDATASectionNode):
|
||
|
'A comment node.'
|
||
|
def getCopyShallow(self, attributes=None):
|
||
|
'Copy the node and set its parentNode.'
|
||
|
return CommentNode(self.parentNode, self.textContent)
|
||
|
|
||
|
def getNodeName(self):
|
||
|
'Get the node name.'
|
||
|
return '#comment'
|
||
|
|
||
|
def getNodeType(self):
|
||
|
'Get the node type.'
|
||
|
return 8
|
||
|
|
||
|
nodeName = property(getNodeName)
|
||
|
nodeType = property(getNodeType)
|
||
|
|
||
|
|
||
|
class DocumentNode:
|
||
|
'A class to parse an xml text and store the elements.'
|
||
|
def __init__(self, fileName, xmlText):
|
||
|
'Initialize.'
|
||
|
self.childNodes = []
|
||
|
self.fileName = fileName
|
||
|
self.idDictionary = {}
|
||
|
self.nameDictionary = {}
|
||
|
self.parentNode = None
|
||
|
self.tagDictionary = {}
|
||
|
self.xmlText = xmlText
|
||
|
createAppendByText(self, xmlText)
|
||
|
|
||
|
def __repr__(self):
|
||
|
'Get the string representation of this xml document.'
|
||
|
output = cStringIO.StringIO()
|
||
|
for childNode in self.childNodes:
|
||
|
childNode.addXML(0, output)
|
||
|
return output.getvalue()
|
||
|
|
||
|
def appendChild(self, elementNode):
|
||
|
'Append child elementNode to the child nodes.'
|
||
|
self.childNodes.append(elementNode)
|
||
|
elementNode.addToIdentifierDictionaries()
|
||
|
return elementNode
|
||
|
|
||
|
def getAttributes(self):
|
||
|
'Get the attributes.'
|
||
|
return {}
|
||
|
|
||
|
def getCascadeBoolean(self, defaultBoolean, key):
|
||
|
'Get the cascade boolean.'
|
||
|
return defaultBoolean
|
||
|
|
||
|
def getCascadeFloat(self, defaultFloat, key):
|
||
|
'Get the cascade float.'
|
||
|
return defaultFloat
|
||
|
|
||
|
def getDocumentElement(self):
|
||
|
'Get the document element.'
|
||
|
if len(self.childNodes) == 0:
|
||
|
return None
|
||
|
return self.childNodes[-1]
|
||
|
|
||
|
def getElementsByLocalName(self, localName):
|
||
|
'Get the descendents which have the given local name.'
|
||
|
return getElementsByLocalName(self.childNodes, localName)
|
||
|
|
||
|
def getImportNameChain(self, suffix=''):
|
||
|
'Get the import name chain with the suffix at the end.'
|
||
|
return suffix
|
||
|
|
||
|
def getNodeName(self):
|
||
|
'Get the node name.'
|
||
|
return '#document'
|
||
|
|
||
|
def getNodeType(self):
|
||
|
'Get the node type.'
|
||
|
return 9
|
||
|
|
||
|
def getOriginalRoot(self):
|
||
|
'Get the original reparsed document element.'
|
||
|
if evaluate.getEvaluatedBoolean(True, self.documentElement, 'getOriginalRoot'):
|
||
|
return DocumentNode(self.fileName, self.xmlText).documentElement
|
||
|
return None
|
||
|
|
||
|
def getOwnerDocument(self):
|
||
|
'Get the owner document.'
|
||
|
return self
|
||
|
|
||
|
attributes = property(getAttributes)
|
||
|
documentElement = property(getDocumentElement)
|
||
|
nodeName = property(getNodeName)
|
||
|
nodeType = property(getNodeType)
|
||
|
ownerDocument = property(getOwnerDocument)
|
||
|
|
||
|
|
||
|
class DocumentTypeMonad(CDATASectionMonad):
|
||
|
'A monad to handle a document type node.'
|
||
|
def getNextMonad(self, character):
|
||
|
'Get the next monad.'
|
||
|
self.input.write(character)
|
||
|
if character == '>':
|
||
|
inputString = self.input.getvalue()
|
||
|
if inputString.endswith('?>'):
|
||
|
textContent = '%s\n' % inputString
|
||
|
self.parentNode.childNodes.append(DocumentTypeNode(self.parentNode, textContent))
|
||
|
return OpenMonad(self.parentNode)
|
||
|
return self
|
||
|
|
||
|
|
||
|
class DocumentTypeNode(CDATASectionNode):
|
||
|
'A document type node.'
|
||
|
def getCopyShallow(self, attributes=None):
|
||
|
'Copy the node and set its parentNode.'
|
||
|
return DocumentTypeNode(self.parentNode, self.textContent)
|
||
|
|
||
|
def getNodeName(self):
|
||
|
'Get the node name.'
|
||
|
return '#forNowDocumentType'
|
||
|
|
||
|
def getNodeType(self):
|
||
|
'Get the node type.'
|
||
|
return 10
|
||
|
|
||
|
nodeName = property(getNodeName)
|
||
|
nodeType = property(getNodeType)
|
||
|
|
||
|
|
||
|
class ElementEndMonad:
|
||
|
'A monad to look for the end of an ElementNode tag.'
|
||
|
def __init__(self, parentNode):
|
||
|
'Initialize.'
|
||
|
self.parentNode = parentNode
|
||
|
|
||
|
def getNextMonad(self, character):
|
||
|
'Get the next monad.'
|
||
|
if character == '>':
|
||
|
return TextMonad(self.parentNode)
|
||
|
return self
|
||
|
|
||
|
|
||
|
class ElementLocalNameMonad:
|
||
|
'A monad to set the local name of an ElementNode.'
|
||
|
def __init__(self, character, parentNode):
|
||
|
'Initialize.'
|
||
|
self.input = cStringIO.StringIO()
|
||
|
self.input.write(character)
|
||
|
self.parentNode = parentNode
|
||
|
|
||
|
def getNextMonad(self, character):
|
||
|
'Get the next monad.'
|
||
|
if character == '[':
|
||
|
if (self.input.getvalue() + character).startswith('![CDATA['):
|
||
|
self.input.write(character)
|
||
|
return CDATASectionMonad(self.input, self.parentNode)
|
||
|
if character == '-':
|
||
|
if (self.input.getvalue() + character).startswith('!--'):
|
||
|
self.input.write(character)
|
||
|
return CommentMonad(self.input, self.parentNode)
|
||
|
if character.isspace():
|
||
|
self.setLocalName()
|
||
|
return ElementReadMonad(self.elementNode)
|
||
|
if character == '/':
|
||
|
self.setLocalName()
|
||
|
self.elementNode.appendSelfToParent()
|
||
|
return ElementEndMonad(self.elementNode.parentNode)
|
||
|
if character == '>':
|
||
|
self.setLocalName()
|
||
|
self.elementNode.appendSelfToParent()
|
||
|
return TextMonad(self.elementNode)
|
||
|
self.input.write(character)
|
||
|
return self
|
||
|
|
||
|
def setLocalName(self):
|
||
|
'Set the class name.'
|
||
|
self.elementNode = ElementNode(self.parentNode)
|
||
|
self.elementNode.localName = self.input.getvalue().lower().strip()
|
||
|
|
||
|
|
||
|
class ElementNode:
|
||
|
'An xml element.'
|
||
|
def __init__(self, parentNode=None):
|
||
|
'Initialize.'
|
||
|
self.attributes = {}
|
||
|
self.childNodes = []
|
||
|
self.localName = ''
|
||
|
self.parentNode = parentNode
|
||
|
self.xmlObject = None
|
||
|
|
||
|
def __repr__(self):
|
||
|
'Get the string representation of this xml document.'
|
||
|
return '%s\n%s\n%s' % (self.localName, self.attributes, self.getTextContent())
|
||
|
|
||
|
def _getAccessibleAttribute(self, attributeName):
|
||
|
'Get the accessible attribute.'
|
||
|
global globalGetAccessibleAttributeSet
|
||
|
if attributeName in globalGetAccessibleAttributeSet:
|
||
|
return getattr(self, attributeName, None)
|
||
|
return None
|
||
|
|
||
|
def addSuffixToID(self, idSuffix):
|
||
|
'Add the suffix to the id.'
|
||
|
if 'id' in self.attributes:
|
||
|
self.attributes['id'] += idSuffix
|
||
|
|
||
|
def addToIdentifierDictionaries(self):
|
||
|
'Add the element to the owner document identifier dictionaries.'
|
||
|
ownerDocument = self.getOwnerDocument()
|
||
|
importNameChain = self.getImportNameChain()
|
||
|
idKey = self.getStrippedAttributesValue('id')
|
||
|
if idKey != None:
|
||
|
ownerDocument.idDictionary[importNameChain + idKey] = self
|
||
|
nameKey = self.getStrippedAttributesValue('name')
|
||
|
if nameKey != None:
|
||
|
euclidean.addElementToListDictionaryIfNotThere(self, importNameChain + nameKey, ownerDocument.nameDictionary)
|
||
|
for tagKey in self.getTagKeys():
|
||
|
euclidean.addElementToListDictionaryIfNotThere(self, tagKey, ownerDocument.tagDictionary)
|
||
|
|
||
|
def addXML(self, depth, output):
|
||
|
'Add xml for this elementNode.'
|
||
|
innerOutput = cStringIO.StringIO()
|
||
|
xml_simple_writer.addXMLFromObjects(depth + 1, self.childNodes, innerOutput)
|
||
|
innerText = innerOutput.getvalue()
|
||
|
xml_simple_writer.addBeginEndInnerXMLTag(self.attributes, depth, innerText, self.localName, output, self.getTextContent())
|
||
|
|
||
|
def appendChild(self, elementNode):
|
||
|
'Append child elementNode to the child nodes.'
|
||
|
self.childNodes.append(elementNode)
|
||
|
elementNode.addToIdentifierDictionaries()
|
||
|
return elementNode
|
||
|
|
||
|
def appendSelfToParent(self):
|
||
|
'Append self to the parentNode.'
|
||
|
self.parentNode.appendChild(self)
|
||
|
|
||
|
def copyXMLChildNodes(self, idSuffix, parentNode):
|
||
|
'Copy the xml childNodes.'
|
||
|
for childNode in self.childNodes:
|
||
|
childNode.getCopy(idSuffix, parentNode)
|
||
|
|
||
|
def getCascadeBoolean(self, defaultBoolean, key):
|
||
|
'Get the cascade boolean.'
|
||
|
if key in self.attributes:
|
||
|
value = evaluate.getEvaluatedBoolean(None, self, key)
|
||
|
if value != None:
|
||
|
return value
|
||
|
return self.parentNode.getCascadeBoolean(defaultBoolean, key)
|
||
|
|
||
|
def getCascadeFloat(self, defaultFloat, key):
|
||
|
'Get the cascade float.'
|
||
|
if key in self.attributes:
|
||
|
value = evaluate.getEvaluatedFloat(None, self, key)
|
||
|
if value != None:
|
||
|
return value
|
||
|
return self.parentNode.getCascadeFloat(defaultFloat, key)
|
||
|
|
||
|
def getChildElementsByLocalName(self, localName):
|
||
|
'Get the childNodes which have the given local name.'
|
||
|
return getChildElementsByLocalName(self.childNodes, localName)
|
||
|
|
||
|
def getCopy(self, idSuffix, parentNode):
|
||
|
'Copy the xml element, set its dictionary and add it to the parentNode.'
|
||
|
matrix4X4 = matrix.getBranchMatrixSetElementNode(self)
|
||
|
attributesCopy = self.attributes.copy()
|
||
|
attributesCopy.update(matrix4X4.getAttributes('matrix.'))
|
||
|
copy = self.getCopyShallow(attributesCopy)
|
||
|
copy.setParentAddToChildNodes(parentNode)
|
||
|
copy.addSuffixToID(idSuffix)
|
||
|
copy.addToIdentifierDictionaries()
|
||
|
self.copyXMLChildNodes(idSuffix, copy)
|
||
|
return copy
|
||
|
|
||
|
def getCopyShallow(self, attributes=None):
|
||
|
'Copy the xml element and set its dictionary and parentNode.'
|
||
|
if attributes == None: # to evade default initialization bug where a dictionary is initialized to the last dictionary
|
||
|
attributes = {}
|
||
|
copyShallow = ElementNode(self.parentNode)
|
||
|
copyShallow.attributes = attributes
|
||
|
copyShallow.localName = self.localName
|
||
|
return copyShallow
|
||
|
|
||
|
def getDocumentElement(self):
|
||
|
'Get the document element.'
|
||
|
return self.getOwnerDocument().getDocumentElement()
|
||
|
|
||
|
def getElementNodeByID(self, idKey):
|
||
|
'Get the xml element by id.'
|
||
|
idDictionary = self.getOwnerDocument().idDictionary
|
||
|
idKey = self.getImportNameChain() + idKey
|
||
|
if idKey in idDictionary:
|
||
|
return idDictionary[idKey]
|
||
|
return None
|
||
|
|
||
|
def getElementNodesByName(self, nameKey):
|
||
|
'Get the xml elements by name.'
|
||
|
nameDictionary = self.getOwnerDocument().nameDictionary
|
||
|
nameKey = self.getImportNameChain() + nameKey
|
||
|
if nameKey in nameDictionary:
|
||
|
return nameDictionary[nameKey]
|
||
|
return None
|
||
|
|
||
|
def getElementNodesByTag(self, tagKey):
|
||
|
'Get the xml elements by tag.'
|
||
|
tagDictionary = self.getOwnerDocument().tagDictionary
|
||
|
if tagKey in tagDictionary:
|
||
|
return tagDictionary[tagKey]
|
||
|
return None
|
||
|
|
||
|
def getElementsByLocalName(self, localName):
|
||
|
'Get the descendents which have the given local name.'
|
||
|
return getElementsByLocalName(self.childNodes, localName)
|
||
|
|
||
|
def getFirstChildByLocalName(self, localName):
|
||
|
'Get the first childNode which has the given class name.'
|
||
|
for childNode in self.childNodes:
|
||
|
if localName.lower() == childNode.getNodeName():
|
||
|
return childNode
|
||
|
return None
|
||
|
|
||
|
def getIDSuffix(self, elementIndex=None):
|
||
|
'Get the id suffix from the dictionary.'
|
||
|
suffix = self.localName
|
||
|
if 'id' in self.attributes:
|
||
|
suffix = self.attributes['id']
|
||
|
if elementIndex == None:
|
||
|
return '_%s' % suffix
|
||
|
return '_%s_%s' % (suffix, elementIndex)
|
||
|
|
||
|
def getImportNameChain(self, suffix=''):
|
||
|
'Get the import name chain with the suffix at the end.'
|
||
|
importName = self.getStrippedAttributesValue('_importName')
|
||
|
if importName != None:
|
||
|
suffix = '%s.%s' % (importName, suffix)
|
||
|
return self.parentNode.getImportNameChain(suffix)
|
||
|
|
||
|
def getNodeName(self):
|
||
|
'Get the node name.'
|
||
|
return self.localName
|
||
|
|
||
|
def getNodeType(self):
|
||
|
'Get the node type.'
|
||
|
return 1
|
||
|
|
||
|
def getOwnerDocument(self):
|
||
|
'Get the owner document.'
|
||
|
return self.parentNode.getOwnerDocument()
|
||
|
|
||
|
def getParser(self):
|
||
|
'Get the parser.'
|
||
|
return self.getOwnerDocument()
|
||
|
|
||
|
def getPaths(self):
|
||
|
'Get all paths.'
|
||
|
if self.xmlObject == None:
|
||
|
return []
|
||
|
return self.xmlObject.getPaths()
|
||
|
|
||
|
def getPreviousElementNode(self):
|
||
|
'Get previous ElementNode if it exists.'
|
||
|
if self.parentNode == None:
|
||
|
return None
|
||
|
previousElementNodeIndex = self.parentNode.childNodes.index(self) - 1
|
||
|
if previousElementNodeIndex < 0:
|
||
|
return None
|
||
|
return self.parentNode.childNodes[previousElementNodeIndex]
|
||
|
|
||
|
def getPreviousVertex(self, defaultVector3=None):
|
||
|
'Get previous vertex if it exists.'
|
||
|
if self.parentNode == None:
|
||
|
return defaultVector3
|
||
|
if self.parentNode.xmlObject == None:
|
||
|
return defaultVector3
|
||
|
if len(self.parentNode.xmlObject.vertexes) < 1:
|
||
|
return defaultVector3
|
||
|
return self.parentNode.xmlObject.vertexes[-1]
|
||
|
|
||
|
def getStrippedAttributesValue(self, keyString):
|
||
|
'Get the stripped attribute value if the length is at least one, otherwise return None.'
|
||
|
if keyString in self.attributes:
|
||
|
strippedAttributesValue = self.attributes[keyString].strip()
|
||
|
if len(strippedAttributesValue) > 0:
|
||
|
return strippedAttributesValue
|
||
|
return None
|
||
|
|
||
|
def getSubChildWithID( self, idReference ):
|
||
|
'Get the childNode which has the idReference.'
|
||
|
for childNode in self.childNodes:
|
||
|
if 'bf:id' in childNode.attributes:
|
||
|
if childNode.attributes['bf:id'] == idReference:
|
||
|
return childNode
|
||
|
subChildWithID = childNode.getSubChildWithID( idReference )
|
||
|
if subChildWithID != None:
|
||
|
return subChildWithID
|
||
|
return None
|
||
|
|
||
|
def getTagKeys(self):
|
||
|
'Get stripped tag keys.'
|
||
|
if 'tags' not in self.attributes:
|
||
|
return []
|
||
|
tagKeys = []
|
||
|
tagString = self.attributes['tags']
|
||
|
if tagString.startswith('='):
|
||
|
tagString = tagString[1 :]
|
||
|
if tagString.startswith('['):
|
||
|
tagString = tagString[1 :]
|
||
|
if tagString.endswith(']'):
|
||
|
tagString = tagString[: -1]
|
||
|
for tagWord in tagString.split(','):
|
||
|
tagKey = tagWord.strip()
|
||
|
if tagKey != '':
|
||
|
tagKeys.append(tagKey)
|
||
|
return tagKeys
|
||
|
|
||
|
def getTextContent(self):
|
||
|
'Get the text from the child nodes.'
|
||
|
if len(self.childNodes) == 0:
|
||
|
return ''
|
||
|
firstNode = self.childNodes[0]
|
||
|
if firstNode.nodeType == 3:
|
||
|
return firstNode.textContent
|
||
|
return ''
|
||
|
|
||
|
def getValueByKey( self, key ):
|
||
|
'Get value by the key.'
|
||
|
if key in evaluate.globalElementValueDictionary:
|
||
|
return evaluate.globalElementValueDictionary[key](self)
|
||
|
if key in self.attributes:
|
||
|
return evaluate.getEvaluatedLinkValue(self, self.attributes[key])
|
||
|
return None
|
||
|
|
||
|
def getVertexes(self):
|
||
|
'Get the vertexes.'
|
||
|
if self.xmlObject == None:
|
||
|
return []
|
||
|
return self.xmlObject.getVertexes()
|
||
|
|
||
|
def getXMLProcessor(self):
|
||
|
'Get the xmlProcessor.'
|
||
|
return self.getDocumentElement().xmlProcessor
|
||
|
|
||
|
def linkObject(self, xmlObject):
|
||
|
'Link self to xmlObject and add xmlObject to archivableObjects.'
|
||
|
self.xmlObject = xmlObject
|
||
|
self.xmlObject.elementNode = self
|
||
|
self.parentNode.xmlObject.archivableObjects.append(self.xmlObject)
|
||
|
|
||
|
def printAllVariables(self):
|
||
|
'Print all variables.'
|
||
|
print('attributes')
|
||
|
print(self.attributes)
|
||
|
print('childNodes')
|
||
|
print(self.childNodes)
|
||
|
print('localName')
|
||
|
print(self.localName)
|
||
|
print('parentNode')
|
||
|
print(self.parentNode.getNodeName())
|
||
|
print('text')
|
||
|
print(self.getTextContent())
|
||
|
print('xmlObject')
|
||
|
print(self.xmlObject)
|
||
|
print('')
|
||
|
|
||
|
def printAllVariablesRoot(self):
|
||
|
'Print all variables and the document element variables.'
|
||
|
self.printAllVariables()
|
||
|
documentElement = self.getDocumentElement()
|
||
|
if documentElement != None:
|
||
|
print('')
|
||
|
print('Root variables:')
|
||
|
documentElement.printAllVariables()
|
||
|
|
||
|
def removeChildNodesFromIDNameParent(self):
|
||
|
'Remove the childNodes from the id and name dictionaries and the childNodes.'
|
||
|
childNodesCopy = self.childNodes[:]
|
||
|
for childNode in childNodesCopy:
|
||
|
childNode.removeFromIDNameParent()
|
||
|
|
||
|
def removeFromIDNameParent(self):
|
||
|
'Remove this from the id and name dictionaries and the childNodes of the parentNode.'
|
||
|
self.removeChildNodesFromIDNameParent()
|
||
|
idKey = self.getStrippedAttributesValue('id')
|
||
|
if idKey != None:
|
||
|
idDictionary = self.getOwnerDocument().idDictionary
|
||
|
idKey = self.getImportNameChain() + idKey
|
||
|
if idKey in idDictionary:
|
||
|
del idDictionary[idKey]
|
||
|
nameKey = self.getStrippedAttributesValue('name')
|
||
|
if nameKey != None:
|
||
|
euclidean.removeElementFromListTable(self, self.getImportNameChain() + nameKey, self.getOwnerDocument().nameDictionary)
|
||
|
for tagKey in self.getTagKeys():
|
||
|
euclidean.removeElementFromListTable(self, tagKey, self.getOwnerDocument().tagDictionary)
|
||
|
if self.parentNode != None:
|
||
|
self.parentNode.childNodes.remove(self)
|
||
|
|
||
|
def setParentAddToChildNodes(self, parentNode):
|
||
|
'Set the parentNode and add this to its childNodes.'
|
||
|
self.parentNode = parentNode
|
||
|
if self.parentNode != None:
|
||
|
self.parentNode.childNodes.append(self)
|
||
|
|
||
|
def setTextContent(self, textContent=''):
|
||
|
'Get the text from the child nodes.'
|
||
|
if len(self.childNodes) == 0:
|
||
|
self.childNodes.append(TextNode(self, textContent))
|
||
|
return
|
||
|
firstNode = self.childNodes[0]
|
||
|
if firstNode.nodeType == 3:
|
||
|
firstNode.textContent = textContent
|
||
|
self.childNodes.append(TextNode(self, textContent))
|
||
|
|
||
|
nodeName = property(getNodeName)
|
||
|
nodeType = property(getNodeType)
|
||
|
ownerDocument = property(getOwnerDocument)
|
||
|
textContent = property(getTextContent)
|
||
|
|
||
|
|
||
|
class ElementReadMonad:
|
||
|
'A monad to read the attributes of the ElementNode tag.'
|
||
|
def __init__(self, elementNode):
|
||
|
'Initialize.'
|
||
|
self.elementNode = elementNode
|
||
|
|
||
|
def getNextMonad(self, character):
|
||
|
'Get the next monad.'
|
||
|
if character.isspace():
|
||
|
return self
|
||
|
if character == '/':
|
||
|
self.elementNode.appendSelfToParent()
|
||
|
return ElementEndMonad(self.elementNode.parentNode)
|
||
|
if character == '>':
|
||
|
self.elementNode.appendSelfToParent()
|
||
|
return TextMonad(self.elementNode)
|
||
|
return KeyMonad(character, self.elementNode)
|
||
|
|
||
|
|
||
|
class KeyMonad:
|
||
|
'A monad to set the key of an attribute of an ElementNode.'
|
||
|
def __init__(self, character, elementNode):
|
||
|
'Initialize.'
|
||
|
self.input = cStringIO.StringIO()
|
||
|
self.input.write(character)
|
||
|
self.elementNode = elementNode
|
||
|
|
||
|
def getNextMonad(self, character):
|
||
|
'Get the next monad.'
|
||
|
if character == '=':
|
||
|
return ValueMonad(self.elementNode, self.input.getvalue().strip())
|
||
|
self.input.write(character)
|
||
|
return self
|
||
|
|
||
|
|
||
|
class OpenChooseMonad(ElementEndMonad):
|
||
|
'A monad to choose the next monad.'
|
||
|
def getNextMonad(self, character):
|
||
|
'Get the next monad.'
|
||
|
if character.isspace():
|
||
|
return self
|
||
|
if character == '?':
|
||
|
input = cStringIO.StringIO()
|
||
|
input.write('<?')
|
||
|
return DocumentTypeMonad(input, self.parentNode)
|
||
|
if character == '/':
|
||
|
return ElementEndMonad(self.parentNode.parentNode)
|
||
|
return ElementLocalNameMonad(character, self.parentNode)
|
||
|
|
||
|
|
||
|
class OpenMonad(ElementEndMonad):
|
||
|
'A monad to handle the open tag character.'
|
||
|
def getNextMonad(self, character):
|
||
|
'Get the next monad.'
|
||
|
if character == '<':
|
||
|
return OpenChooseMonad(self.parentNode)
|
||
|
return self
|
||
|
|
||
|
|
||
|
class TextMonad:
|
||
|
'A monad to handle the open tag character and set the text.'
|
||
|
def __init__(self, parentNode):
|
||
|
'Initialize.'
|
||
|
self.input = cStringIO.StringIO()
|
||
|
self.parentNode = parentNode
|
||
|
|
||
|
def getNextMonad(self, character):
|
||
|
'Get the next monad.'
|
||
|
if character == '<':
|
||
|
inputString = self.input.getvalue().strip()
|
||
|
if len(inputString) > 0:
|
||
|
self.parentNode.childNodes.append(TextNode(self.parentNode, inputString))
|
||
|
return OpenChooseMonad(self.parentNode)
|
||
|
self.input.write(character)
|
||
|
return self
|
||
|
|
||
|
|
||
|
class TextNode(CDATASectionNode):
|
||
|
'A text node.'
|
||
|
def addXML(self, depth, output):
|
||
|
'Add xml for this text node.'
|
||
|
pass
|
||
|
|
||
|
def getCopyShallow(self, attributes=None):
|
||
|
'Copy the node and set its parentNode.'
|
||
|
return TextNode(self.parentNode, self.textContent)
|
||
|
|
||
|
def getNodeName(self):
|
||
|
'Get the node name.'
|
||
|
return '#text'
|
||
|
|
||
|
def getNodeType(self):
|
||
|
'Get the node type.'
|
||
|
return 3
|
||
|
|
||
|
nodeName = property(getNodeName)
|
||
|
nodeType = property(getNodeType)
|
||
|
|
||
|
|
||
|
class ValueMonad:
|
||
|
'A monad to set the value of an attribute of an ElementNode.'
|
||
|
def __init__(self, elementNode, key):
|
||
|
'Initialize.'
|
||
|
self.elementNode = elementNode
|
||
|
self.input = cStringIO.StringIO()
|
||
|
self.key = key
|
||
|
self.quoteCharacter = None
|
||
|
|
||
|
def getNextMonad(self, character):
|
||
|
'Get the next monad.'
|
||
|
if self.quoteCharacter == None:
|
||
|
if character == '"' or character == "'":
|
||
|
self.quoteCharacter = character
|
||
|
return self
|
||
|
if self.quoteCharacter == character:
|
||
|
self.elementNode.attributes[self.key] = self.input.getvalue()
|
||
|
return ElementReadMonad(self.elementNode)
|
||
|
self.input.write(character)
|
||
|
return self
|
||
|
|