diff -r 000000000000 -r b622defdfd98 minixsv/minidomif.py --- /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) +