#
# # 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)