minixsv/elemtreeif.py
author lbessard
Sun, 09 Dec 2007 17:07:45 +0100
changeset 127 436268f31dae
parent 0 b622defdfd98
permissions -rw-r--r--
Adding contextual menu on LD_Contact, LD_Coil, LD_PowerRail and SFC_ActionBlock
#
# minixsv, Release 0.3
# file: elemtreeif.py
#
# XML interface class to elementtree toolkit by Fredrik Lundh
#
# 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
import urlparse
from xmlifbase               import *
from xml.parsers.expat       import ExpatError
from elementtree.ElementTree import *

#########################################################
# Derived interface class for elementtree toolkit

class ElementTreeInterface (XmlInterfaceBase):
    #####################################################
    # for description of the interface methods see xmlifbase.py
    #####################################################

    def __init__ (self, verbose):
        XmlInterfaceBase.__init__ (self, verbose)
        if self.verbose:
            print "Using elementtree interface module..."


    def parse (self, file, baseUrl):
        url    = self._convertToUrl(file)
        absUrl = self._convertToAbsUrl (url, baseUrl)
        fp     = urllib.urlopen (absUrl)
        try:
            tree = ElementTree()
            parser = ExtXMLTreeBuilder(file, url, absUrl)
            tree.parse(fp, parser)
        finally:
            fp.close()

        return TreeWrapper(self, tree)


    def parseString (self, text):
        parser = ExtXMLTreeBuilder("", "", "")
        parser.feed(text)
        return TreeWrapper (self, ElementTree(parser.close()))


#########################################################
# Wrapper class for ElementTree class

class TreeWrapper (TreeWrapperBase):

    def getRootNode (self):
        return ElementWrapper(self.xmlIf, self, self.tree.getroot())


    def insertSubtree (self, nextSiblingWrapper, file, baseUrl):
        subTreeWrapper = self.xmlIf.extParse (file, baseUrl)
        assert self.getRootNode().getTagName() == subTreeWrapper.getRootNode().getTagName(),\
               "%s: line %d: root node of include file %s does not match!" %(self.getRootNode().getUrl(), self.getRootNode().getStartLineNumber(), file)

        if nextSiblingWrapper != None:
            insertIndex = self.tree.getroot().getchildren().index (nextSiblingWrapper.element)
        else:
            insertIndex = 0
        elementWrapperList = subTreeWrapper.getRootNode().getChildren()
        elementWrapperList.reverse()
        for elementWrapper in elementWrapperList:
            self.tree.getroot().insert (insertIndex, elementWrapper.element)

           
#########################################################
# Wrapper class for Element class

class ElementWrapper (ElementWrapperBase):

    def getTagName (self):
        return self.element.tag


    def getChildren (self, filterTag=None):
        if filterTag in (None, '*'):
            children = self.element.getchildren()
        else:
            children = self.element.findall(filterTag)

        return map(lambda element: ElementWrapper(self.xmlIf, self.treeWrapper, element), children)


    def getFirstChild (self, filterTag=None):
        # replace base method (performance optimized)
        if filterTag in (None, '*'):
            children = self.element.getchildren()
            if children != []:
                element = children[0]
            else:
                element = None
        else:
            element = self.element.find(filterTag)

        if element != None:
            return ElementWrapper(self.xmlIf, self.treeWrapper, element)
        else:
            return None


    def getElementsByTagName (self, filterTag=None):
        if filterTag == '*':
            filterTag = None
        elements = self.element.getiterator (filterTag)

        return map(lambda element: ElementWrapper(self.xmlIf, self.treeWrapper, element), elements)


    def removeChild (self, childElementWrapper):
        self.element.remove (childElementWrapper.element)


    def getAttributeDict (self):
        return self.element.attrib


    def getAttribute (self, attributeName):
        if self.element.attrib.has_key(attributeName):
            return self.element.attrib[attributeName]
        else:
            return None

        
    def hasAttribute (self, attributeName):
        return self.element.attrib.has_key(attributeName)


    def setAttribute (self, attributeName, attributeValue):
        self.element.attrib[attributeName] = attributeValue


    ###############################################################
    # Caution! Currently returns only the element value until the first
    #          child element!!
    def getElementValue (self):
        if self.element.text != None:
            return self.element.text
        else:
            return ""


    ###############################################################
    # Caution! Currently only sets the element value until the first
    #          child element!!
    def setElementValue (self, value):
        self.element.text = value


###################################################
# Element tree builder class derived from XMLTreeBuilder
# extended to store related line numbers in the Element object

class ExtXMLTreeBuilder (XMLTreeBuilder):
    def __init__(self, filePath, url, absUrl):
        self.filePath = filePath
        self.url      = url
        self.absUrl   = absUrl
        XMLTreeBuilder.__init__(self)

    def _start(self, tag, attrib_in):
        element = XMLTreeBuilder._start(self, tag, attrib_in)
        element.filePath = self.filePath
        element.url      = self.url
        element.absUrl   = self.absUrl
        element.startLineNumber = self._parser.ErrorLineNumber
        return element
        
    def _end(self, tag):
        element = XMLTreeBuilder._end(self, tag)
        element.endLineNumber = self._parser.ErrorLineNumber
        return element