minixsv/minidomif.py
changeset 0 b622defdfd98
equal deleted inserted replaced
-1:000000000000 0:b622defdfd98
       
     1 #
       
     2 # # minixsv, Release 0.3
       
     3 # file: minidomif.py
       
     4 #
       
     5 # XML interface class to minidom
       
     6 #
       
     7 # history:
       
     8 # 2004-09-09 rl   created
       
     9 # 2004-09-22 rl   XML interface classes completely re-designed
       
    10 # 2004-09-23 rl   added filename and line number support
       
    11 # 2004-09-29 rl   URL processing added
       
    12 # 2004-10-01 rl   URL processing improved
       
    13 # 2004-10-12 rl   XML text processing added
       
    14 #
       
    15 # Copyright (c) 2004 by Roland Leuthe.  All rights reserved.
       
    16 #
       
    17 # --------------------------------------------------------------------
       
    18 # The minixsv XML schema validator is
       
    19 #
       
    20 # Copyright (c) 2004 by Roland Leuthe
       
    21 #
       
    22 # By obtaining, using, and/or copying this software and/or its
       
    23 # associated documentation, you agree that you have read, understood,
       
    24 # and will comply with the following terms and conditions:
       
    25 #
       
    26 # Permission to use, copy, modify, and distribute this software and
       
    27 # its associated documentation for any purpose and without fee is
       
    28 # hereby granted, provided that the above copyright notice appears in
       
    29 # all copies, and that both that copyright notice and this permission
       
    30 # notice appear in supporting documentation, and that the name of
       
    31 # the author not be used in advertising or publicity
       
    32 # pertaining to distribution of the software without specific, written
       
    33 # prior permission.
       
    34 #
       
    35 # THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
       
    36 # TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
       
    37 # ABILITY AND FITNESS.  IN NO EVENT SHALL THE AUTHOR
       
    38 # BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
       
    39 # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
       
    40 # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
       
    41 # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
       
    42 # OF THIS SOFTWARE.
       
    43 # --------------------------------------------------------------------
       
    44 
       
    45 import urllib
       
    46 from xmlifbase            import *
       
    47 from xml.parsers.expat    import ExpatError
       
    48 from xml.dom.expatbuilder import ExpatBuilderNS
       
    49 from xml.dom.minidom      import *
       
    50 
       
    51 
       
    52 class MiniDomInterface (XmlInterfaceBase):
       
    53     #####################################################
       
    54     # for description of the interface methods see xmlifbase.py
       
    55     #####################################################
       
    56 
       
    57     def __init__ (self, verbose):
       
    58         XmlInterfaceBase.__init__ (self, verbose)
       
    59         if self.verbose:
       
    60             print "Using minidom interface module..."
       
    61 
       
    62 
       
    63     def parse (self, file, baseUrl):
       
    64         url    = self._convertToUrl(file)
       
    65         absUrl = self._convertToAbsUrl (url, baseUrl)
       
    66         fp     = urllib.urlopen (absUrl)
       
    67         try:
       
    68             builder = ExtExpatBuilderNS(file, url, absUrl)
       
    69             tree = builder.parseFile(fp)
       
    70         finally:
       
    71             fp.close()
       
    72 
       
    73         return TreeWrapper(self, tree)
       
    74 
       
    75 
       
    76     def parseString (self, text):
       
    77         builder = ExtExpatBuilderNS("", "", "")
       
    78         tree = builder.parseString (text)
       
    79         return TreeWrapper (self, tree)
       
    80 
       
    81 
       
    82 #########################################################
       
    83 # Wrapper class for minidom.Document class
       
    84 
       
    85 class TreeWrapper (TreeWrapperBase):
       
    86 
       
    87     def getRootNode (self):
       
    88         return ElementWrapper (self.xmlIf, self, self.tree.documentElement)
       
    89 
       
    90     def insertSubtree (self, nextSiblingWrapper, file, baseUrl):
       
    91         subTreeWrapper = self.xmlIf.extParse (file, baseUrl)
       
    92         assert self.getRootNode().getLocalName() == subTreeWrapper.getRootNode().getLocalName(),\
       
    93                "%s: line %d: root node of include file %s does not match!" %(self.getRootNode().getUrl(), self.getRootNode().getStartLineNumber(), file)
       
    94 
       
    95         elementWrapperList = subTreeWrapper.getRootNode().getChildren()
       
    96         for elementWrapper in elementWrapperList:
       
    97             if nextSiblingWrapper != None:
       
    98                 self.tree.documentElement.insertBefore(elementWrapper.element, nextSiblingWrapper.element)
       
    99             else:
       
   100                 self.tree.documentElement.appendChild(elementWrapper.element)
       
   101 
       
   102 
       
   103 #########################################################
       
   104 # Wrapper class for minidom.Document class
       
   105 
       
   106 class ElementWrapper (ElementWrapperBase):
       
   107 
       
   108     def getTagName (self):
       
   109         return self.element.tagName
       
   110 
       
   111 
       
   112     def getLocalName (self):
       
   113         # base method replaced (optimized method)
       
   114         return self.element.localName
       
   115 
       
   116 
       
   117     def getNamespaceURI (self):
       
   118         # base method replaced (optimized method)
       
   119         return self.element.namespaceURI
       
   120 
       
   121 
       
   122     def getChildren (self, filterTag=None):
       
   123         return map(lambda element: ElementWrapper(self.xmlIf, self.treeWrapper, element), self._getElemNodes(filterTag))
       
   124 
       
   125 
       
   126     def getElementsByTagName (self, filterTag=None):
       
   127         if filterTag == None:
       
   128             filterTag = '*'
       
   129         return map(lambda element: ElementWrapper(self.xmlIf, self.treeWrapper, element), self.element.getElementsByTagName(filterTag))
       
   130 
       
   131 
       
   132     def removeChild (self, childElementWrapper):
       
   133         self.element.removeChild(childElementWrapper.element)
       
   134 
       
   135 
       
   136     def getAttributeDict (self):
       
   137         """Return dictionary of attributes"""
       
   138         attribDict = {}
       
   139         for attrName, attrValue in self.element.attributes.items():
       
   140             attribDict[attrName] = attrValue
       
   141         return attribDict
       
   142 
       
   143 
       
   144     def getAttribute (self, attributeName):
       
   145         if self.element.attributes.has_key (attributeName):
       
   146             return self.element.getAttribute (attributeName)
       
   147         else:
       
   148             return None
       
   149 
       
   150 
       
   151     def hasAttribute (self, attributeName):
       
   152         return self.element.attributes.has_key (attributeName)
       
   153 
       
   154 
       
   155     def setAttribute (self, attributeName, attributeValue):
       
   156         if not self.hasAttribute(attributeName):
       
   157             self.element.setAttributeNode (self.treeWrapper.tree.createAttribute (attributeName))
       
   158         self.element.setAttribute(attributeName, attributeValue)
       
   159 
       
   160 
       
   161     ###############################################################
       
   162     # Caution! Currently returns only the first text node!!
       
   163     def getElementValue (self):
       
   164         textNodes = self._getTextNodes ()
       
   165         if textNodes:
       
   166             return textNodes[0].data
       
   167         else:
       
   168             return ""
       
   169 
       
   170 
       
   171     ###############################################################
       
   172     # Caution! Currently only sets the first text node!!
       
   173     def setElementValue (self, value):
       
   174         textNodes = self._getTextNodes()
       
   175         if textNodes:
       
   176             textNodes[0].data = value
       
   177 
       
   178 
       
   179     ###############################################################
       
   180     # PRIVATE methods
       
   181     ###############################################################
       
   182 
       
   183     def _getTextNodes (self):
       
   184         """Return list of TEXT nodes."""
       
   185         return filter (lambda e: (e.nodeType == Node.TEXT_NODE),        # - only TEXT-NODES
       
   186                        self.element.childNodes)                         # from element's child nodes
       
   187 
       
   188 
       
   189     def _getElemNodes (self, filterTag):
       
   190         """Return list of ELEMENT nodes and check for tag name (if given)."""
       
   191         return filter (lambda e: (e.nodeType == Node.ELEMENT_NODE) and                          # - only ELEMENTs
       
   192                                  (not filterTag or filterTag == '*' or e.tagName == filterTag), # - if tagName given --> check tagName
       
   193                        self.element.childNodes)                                                 # from element's nodes
       
   194 
       
   195 
       
   196 
       
   197 ###################################################
       
   198 # Expat builder class derived from ExpatBuilderNS
       
   199 # extended to store related line numbers in the node object
       
   200 
       
   201 class ExtExpatBuilderNS (ExpatBuilderNS):
       
   202     def __init__ (self, filePath, url, absUrl):
       
   203         self.filePath = filePath
       
   204         self.url      = url
       
   205         self.absUrl   = absUrl
       
   206         ExpatBuilderNS.__init__(self)
       
   207 
       
   208     def start_element_handler(self, name, attributes):
       
   209         ExpatBuilderNS.start_element_handler(self, name, attributes)
       
   210         self.curNode.url      = self.url
       
   211         self.curNode.absUrl   = self.absUrl
       
   212         self.curNode.filePath = self.filePath
       
   213         self.curNode.startLineNumber = self.getParser().ErrorLineNumber
       
   214 
       
   215     def end_element_handler(self, name):
       
   216         self.curNode.endLineNumber = self.getParser().ErrorLineNumber
       
   217         ExpatBuilderNS.end_element_handler(self, name)
       
   218