minixsv/minidomif.py
changeset 0 b622defdfd98
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/minixsv/minidomif.py	Wed Jan 31 16:31:39 2007 +0100
@@ -0,0 +1,218 @@
+#
+# # minixsv, Release 0.3
+# file: minidomif.py
+#
+# XML interface class to minidom
+#
+# history:
+# 2004-09-09 rl   created
+# 2004-09-22 rl   XML interface classes completely re-designed
+# 2004-09-23 rl   added filename and line number support
+# 2004-09-29 rl   URL processing added
+# 2004-10-01 rl   URL processing improved
+# 2004-10-12 rl   XML text processing added
+#
+# Copyright (c) 2004 by Roland Leuthe.  All rights reserved.
+#
+# --------------------------------------------------------------------
+# The minixsv XML schema validator is
+#
+# Copyright (c) 2004 by Roland Leuthe
+#
+# By obtaining, using, and/or copying this software and/or its
+# associated documentation, you agree that you have read, understood,
+# and will comply with the following terms and conditions:
+#
+# Permission to use, copy, modify, and distribute this software and
+# its associated documentation for any purpose and without fee is
+# hereby granted, provided that the above copyright notice appears in
+# all copies, and that both that copyright notice and this permission
+# notice appear in supporting documentation, and that the name of
+# the author not be used in advertising or publicity
+# pertaining to distribution of the software without specific, written
+# prior permission.
+#
+# THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
+# ABILITY AND FITNESS.  IN NO EVENT SHALL THE AUTHOR
+# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+# --------------------------------------------------------------------
+
+import urllib
+from xmlifbase            import *
+from xml.parsers.expat    import ExpatError
+from xml.dom.expatbuilder import ExpatBuilderNS
+from xml.dom.minidom      import *
+
+
+class MiniDomInterface (XmlInterfaceBase):
+    #####################################################
+    # for description of the interface methods see xmlifbase.py
+    #####################################################
+
+    def __init__ (self, verbose):
+        XmlInterfaceBase.__init__ (self, verbose)
+        if self.verbose:
+            print "Using minidom interface module..."
+
+
+    def parse (self, file, baseUrl):
+        url    = self._convertToUrl(file)
+        absUrl = self._convertToAbsUrl (url, baseUrl)
+        fp     = urllib.urlopen (absUrl)
+        try:
+            builder = ExtExpatBuilderNS(file, url, absUrl)
+            tree = builder.parseFile(fp)
+        finally:
+            fp.close()
+
+        return TreeWrapper(self, tree)
+
+
+    def parseString (self, text):
+        builder = ExtExpatBuilderNS("", "", "")
+        tree = builder.parseString (text)
+        return TreeWrapper (self, tree)
+
+
+#########################################################
+# Wrapper class for minidom.Document class
+
+class TreeWrapper (TreeWrapperBase):
+
+    def getRootNode (self):
+        return ElementWrapper (self.xmlIf, self, self.tree.documentElement)
+
+    def insertSubtree (self, nextSiblingWrapper, file, baseUrl):
+        subTreeWrapper = self.xmlIf.extParse (file, baseUrl)
+        assert self.getRootNode().getLocalName() == subTreeWrapper.getRootNode().getLocalName(),\
+               "%s: line %d: root node of include file %s does not match!" %(self.getRootNode().getUrl(), self.getRootNode().getStartLineNumber(), file)
+
+        elementWrapperList = subTreeWrapper.getRootNode().getChildren()
+        for elementWrapper in elementWrapperList:
+            if nextSiblingWrapper != None:
+                self.tree.documentElement.insertBefore(elementWrapper.element, nextSiblingWrapper.element)
+            else:
+                self.tree.documentElement.appendChild(elementWrapper.element)
+
+
+#########################################################
+# Wrapper class for minidom.Document class
+
+class ElementWrapper (ElementWrapperBase):
+
+    def getTagName (self):
+        return self.element.tagName
+
+
+    def getLocalName (self):
+        # base method replaced (optimized method)
+        return self.element.localName
+
+
+    def getNamespaceURI (self):
+        # base method replaced (optimized method)
+        return self.element.namespaceURI
+
+
+    def getChildren (self, filterTag=None):
+        return map(lambda element: ElementWrapper(self.xmlIf, self.treeWrapper, element), self._getElemNodes(filterTag))
+
+
+    def getElementsByTagName (self, filterTag=None):
+        if filterTag == None:
+            filterTag = '*'
+        return map(lambda element: ElementWrapper(self.xmlIf, self.treeWrapper, element), self.element.getElementsByTagName(filterTag))
+
+
+    def removeChild (self, childElementWrapper):
+        self.element.removeChild(childElementWrapper.element)
+
+
+    def getAttributeDict (self):
+        """Return dictionary of attributes"""
+        attribDict = {}
+        for attrName, attrValue in self.element.attributes.items():
+            attribDict[attrName] = attrValue
+        return attribDict
+
+
+    def getAttribute (self, attributeName):
+        if self.element.attributes.has_key (attributeName):
+            return self.element.getAttribute (attributeName)
+        else:
+            return None
+
+
+    def hasAttribute (self, attributeName):
+        return self.element.attributes.has_key (attributeName)
+
+
+    def setAttribute (self, attributeName, attributeValue):
+        if not self.hasAttribute(attributeName):
+            self.element.setAttributeNode (self.treeWrapper.tree.createAttribute (attributeName))
+        self.element.setAttribute(attributeName, attributeValue)
+
+
+    ###############################################################
+    # Caution! Currently returns only the first text node!!
+    def getElementValue (self):
+        textNodes = self._getTextNodes ()
+        if textNodes:
+            return textNodes[0].data
+        else:
+            return ""
+
+
+    ###############################################################
+    # Caution! Currently only sets the first text node!!
+    def setElementValue (self, value):
+        textNodes = self._getTextNodes()
+        if textNodes:
+            textNodes[0].data = value
+
+
+    ###############################################################
+    # PRIVATE methods
+    ###############################################################
+
+    def _getTextNodes (self):
+        """Return list of TEXT nodes."""
+        return filter (lambda e: (e.nodeType == Node.TEXT_NODE),        # - only TEXT-NODES
+                       self.element.childNodes)                         # from element's child nodes
+
+
+    def _getElemNodes (self, filterTag):
+        """Return list of ELEMENT nodes and check for tag name (if given)."""
+        return filter (lambda e: (e.nodeType == Node.ELEMENT_NODE) and                          # - only ELEMENTs
+                                 (not filterTag or filterTag == '*' or e.tagName == filterTag), # - if tagName given --> check tagName
+                       self.element.childNodes)                                                 # from element's nodes
+
+
+
+###################################################
+# Expat builder class derived from ExpatBuilderNS
+# extended to store related line numbers in the node object
+
+class ExtExpatBuilderNS (ExpatBuilderNS):
+    def __init__ (self, filePath, url, absUrl):
+        self.filePath = filePath
+        self.url      = url
+        self.absUrl   = absUrl
+        ExpatBuilderNS.__init__(self)
+
+    def start_element_handler(self, name, attributes):
+        ExpatBuilderNS.start_element_handler(self, name, attributes)
+        self.curNode.url      = self.url
+        self.curNode.absUrl   = self.absUrl
+        self.curNode.filePath = self.filePath
+        self.curNode.startLineNumber = self.getParser().ErrorLineNumber
+
+    def end_element_handler(self, name):
+        self.curNode.endLineNumber = self.getParser().ErrorLineNumber
+        ExpatBuilderNS.end_element_handler(self, name)
+