minixsv/xsvalSchema.py
changeset 152 dcfe7c07ba1c
parent 151 aaa80b48bead
child 153 f0e8e7f58a5a
equal deleted inserted replaced
151:aaa80b48bead 152:dcfe7c07ba1c
     1 #
       
     2 # minixsv, Release 0.3
       
     3 # file: xsvalSchema.py
       
     4 #
       
     5 # Derived validator class (for validation of schema files)
       
     6 #
       
     7 # history:
       
     8 # 2004-10-07 rl   created
       
     9 #
       
    10 # Copyright (c) 2004 by Roland Leuthe.  All rights reserved.
       
    11 #
       
    12 # --------------------------------------------------------------------
       
    13 # The minixsv XML schema validator is
       
    14 #
       
    15 # Copyright (c) 2004 by Roland Leuthe
       
    16 #
       
    17 # By obtaining, using, and/or copying this software and/or its
       
    18 # associated documentation, you agree that you have read, understood,
       
    19 # and will comply with the following terms and conditions:
       
    20 #
       
    21 # Permission to use, copy, modify, and distribute this software and
       
    22 # its associated documentation for any purpose and without fee is
       
    23 # hereby granted, provided that the above copyright notice appears in
       
    24 # all copies, and that both that copyright notice and this permission
       
    25 # notice appear in supporting documentation, and that the name of
       
    26 # the author not be used in advertising or publicity
       
    27 # pertaining to distribution of the software without specific, written
       
    28 # prior permission.
       
    29 #
       
    30 # THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
       
    31 # TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
       
    32 # ABILITY AND FITNESS.  IN NO EVENT SHALL THE AUTHOR
       
    33 # BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
       
    34 # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
       
    35 # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
       
    36 # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
       
    37 # OF THIS SOFTWARE.
       
    38 # --------------------------------------------------------------------
       
    39 
       
    40 from xsvalErrorHandler import *
       
    41 from xsvalBase import XsValBase
       
    42 
       
    43 ###########################################################
       
    44 #  Derived validator class for validating one input schema file against the XML rules file
       
    45 
       
    46 class XsValSchema (XsValBase):
       
    47 
       
    48     ########################################
       
    49     # overloaded validate method
       
    50     #
       
    51     def validate (self, inputTree, xsdTree):
       
    52         XsValBase.validate(self, inputTree, xsdTree)
       
    53         self._checkSchemaSecondLevel()
       
    54 
       
    55 
       
    56     ########################################
       
    57     # additional checks for schema files which are not covered by "xsStructs.xsd"
       
    58     #
       
    59     def _checkSchemaSecondLevel(self):
       
    60         self._checkElementNodesSecondLevel()
       
    61         self._checkGroupNodesSecondLevel()
       
    62         self._checkAttrGroupNodesSecondLevel()
       
    63         self._checkAttributeNodesSecondLevel()
       
    64 
       
    65         self._checkSimpleTypesSecondLevel()
       
    66 
       
    67 
       
    68     ########################################
       
    69     # additional checks for element nodes
       
    70     #
       
    71     def _checkElementNodesSecondLevel(self):
       
    72         self.inputElementDict = {}
       
    73         for inputNode in self.inputRoot.getChildrenNS(self.inputNSAlias, "element"):
       
    74             self.inputElementDict[inputNode.getAttribute("name")] = inputNode
       
    75 
       
    76         elementNodes = self.inputRoot.getElementsByTagNameNS (self.inputNSAlias, "element")
       
    77         for elementNode in elementNodes:
       
    78             if not elementNode.hasAttribute("name") and not elementNode.hasAttribute("ref"):
       
    79                 self._addError ("Element must have 'name' or 'ref' attribute!", elementNode)
       
    80                 continue
       
    81 
       
    82             if elementNode.hasAttribute("name") and elementNode.hasAttribute("ref"):
       
    83                 self._addError ("Element must not have 'name' and 'ref' attribute!", elementNode)
       
    84                 continue
       
    85 
       
    86             if elementNode.hasAttribute("ref"):
       
    87                 elementRef = self.xmlIf.extractLocalName(elementNode.getAttribute("ref"))
       
    88                 if not self.inputElementDict.has_key(elementRef):
       
    89                     self._addError ("Reference to undefined element '%s'!" %(elementRef), elementNode)
       
    90 
       
    91             complexTypeNode = elementNode.getFirstChildNS (self.inputNSAlias, "complexType")
       
    92             simpleTypeNode = elementNode.getFirstChildNS (self.inputNSAlias, "simpleType")
       
    93             if elementNode.hasAttribute("type") and (complexTypeNode != None or simpleTypeNode != None):
       
    94                 self._addError ("Element has type attribute and type definition!", elementNode)
       
    95             if not elementNode.hasAttribute("type") and complexTypeNode == None and simpleTypeNode == None:
       
    96                 self._addWarning ("Element has no type attribute and no type definition!", elementNode)
       
    97 
       
    98             minOccurs = elementNode.getAttributeOrDefault("minOccurs", "1")
       
    99             maxOccurs = elementNode.getAttributeOrDefault("maxOccurs", "1")
       
   100             if maxOccurs != "unbounded":
       
   101                 if string.atoi(minOccurs) > string.atoi(maxOccurs):
       
   102                     self._addError ("Attribute minOccurs > maxOccurs!", elementNode)
       
   103 
       
   104 
       
   105     ########################################
       
   106     # additional checks for group nodes
       
   107     #
       
   108     def _checkGroupNodesSecondLevel(self):
       
   109         self.inputGroupDict = {}
       
   110         for groupNode in self.inputRoot.getChildrenNS(self.inputNSAlias, "group"):
       
   111             self.inputGroupDict[groupNode.getAttribute("name")] = groupNode
       
   112 
       
   113         groupNodes = self.inputRoot.getElementsByTagNameNS (self.inputNSAlias, "group")
       
   114         for groupNode in groupNodes:
       
   115             if groupNode.hasAttribute("ref"):
       
   116                 groupRef = self.xmlIf.extractLocalName(groupNode.getAttribute("ref"))
       
   117                 if not self.inputGroupDict.has_key(groupRef):
       
   118                     self._addError ("Reference to undefined group '%s'!" %(groupRef), groupNode)
       
   119 
       
   120 
       
   121     ########################################
       
   122     # additional checks for attributeGroup nodes
       
   123     #
       
   124     def _checkAttrGroupNodesSecondLevel(self):
       
   125         self.inputAttrGroupDict = {}
       
   126         for attrGroupNode in self.inputRoot.getChildrenNS(self.inputNSAlias, "attrGroup"):
       
   127             self.inputAttrGroupDict[attrGroupNode.getAttribute("name")] = attrGroupNode
       
   128 
       
   129         attrGroupNodes = self.inputRoot.getElementsByTagNameNS (self.inputNSAlias, "attrGroup")
       
   130         for attrGroupNode in attrGroupNodes:
       
   131             if attrGroupNode.hasAttribute("ref"):
       
   132                 attrGroupRef = self.xmlIf.extractLocalName(attrGroupNode.getAttribute("ref"))
       
   133                 if not self.inputAttrGroupDict.has_key(attrGroupRef):
       
   134                     self._addError ("Reference to undefined attribute group '%s'!" %(attrGroupRef), attrGroupNode)
       
   135 
       
   136 
       
   137     ########################################
       
   138     # additional checks for attribute nodes
       
   139     #
       
   140     def _checkAttributeNodesSecondLevel(self):
       
   141         attributeNodes = self.inputRoot.getElementsByTagNameNS (self.inputNSAlias, "attribute")
       
   142         for attributeNode in attributeNodes:
       
   143             if not attributeNode.hasAttribute("name") and not attributeNode.hasAttribute("ref"):
       
   144                 self._addError ("Attribute must have 'name' or 'ref' attribute!", attributeNode)
       
   145                 continue
       
   146 
       
   147             if attributeNode.getAttribute("use") == "required" and attributeNode.hasAttribute("default"):
       
   148                 self._addError ("Attribute 'default' is not allowed, because 'use' is 'required'!", attributeNode)
       
   149             elif attributeNode.hasAttribute("default") and attributeNode.hasAttribute("fixed"):
       
   150                 self._addError ("Attribute must not have 'default' AND 'fixed' attribute!", attributeNode)
       
   151 
       
   152 
       
   153     ########################################
       
   154     # additional checks for simple types
       
   155     #
       
   156     def _checkSimpleTypesSecondLevel(self):
       
   157         restrictionNodes, dummy = self.inputRoot.getXPathList (".//simpleType/restriction", self.inputNSAlias)
       
   158         for restrictionNode in restrictionNodes:
       
   159             if not restrictionNode.hasAttribute("base") and restrictionNode.getFirstChildNS (self.inputNSAlias, "simpleType") == None:
       
   160                 self._addError ("Simple type restriction must have 'base' attribute or 'simpleType' child tag!", restrictionNode)
       
   161 
       
   162             minExcl = restrictionNode.getFirstChildNS(self.inputNSAlias, "minExclusive")
       
   163             minIncl = restrictionNode.getFirstChildNS(self.inputNSAlias, "minInclusive")
       
   164             if minExcl != None and minIncl != None:
       
   165                 self._addError ("Restriction attributes 'minExclusive' and 'minInclusive' cannot be defined together!", restrictionNode)
       
   166             maxExcl = restrictionNode.getFirstChildNS(self.inputNSAlias, "maxExclusive")
       
   167             maxIncl = restrictionNode.getFirstChildNS(self.inputNSAlias, "maxInclusive")
       
   168             if maxExcl != None and maxIncl != None:
       
   169                 self._addError ("Restriction attributes 'maxExclusive' and 'maxInclusive' cannot be defined together!", restrictionNode)
       
   170 
       
   171         listNodes = self.inputRoot.getElementsByTagNameNS (self.inputNSAlias, "list")
       
   172         for listNode in listNodes:
       
   173             if not listNode.hasAttribute("itemType") and restrictionNode.getFirstChildNS (self.inputNSAlias, "simpleType") == None:
       
   174                 self._addError ("List type must have 'itemType' attribute or 'simpleType' child tag!", listNode)
       
   175 
       
   176