diff -r 000000000000 -r b622defdfd98 minixsv/xsvalSchema.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/minixsv/xsvalSchema.py Wed Jan 31 16:31:39 2007 +0100 @@ -0,0 +1,176 @@ +# +# minixsv, Release 0.3 +# file: xsvalSchema.py +# +# Derived validator class (for validation of schema files) +# +# history: +# 2004-10-07 rl created +# +# 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. +# -------------------------------------------------------------------- + +from xsvalErrorHandler import * +from xsvalBase import XsValBase + +########################################################### +# Derived validator class for validating one input schema file against the XML rules file + +class XsValSchema (XsValBase): + + ######################################## + # overloaded validate method + # + def validate (self, inputTree, xsdTree): + XsValBase.validate(self, inputTree, xsdTree) + self._checkSchemaSecondLevel() + + + ######################################## + # additional checks for schema files which are not covered by "xsStructs.xsd" + # + def _checkSchemaSecondLevel(self): + self._checkElementNodesSecondLevel() + self._checkGroupNodesSecondLevel() + self._checkAttrGroupNodesSecondLevel() + self._checkAttributeNodesSecondLevel() + + self._checkSimpleTypesSecondLevel() + + + ######################################## + # additional checks for element nodes + # + def _checkElementNodesSecondLevel(self): + self.inputElementDict = {} + for inputNode in self.inputRoot.getChildrenNS(self.inputNSAlias, "element"): + self.inputElementDict[inputNode.getAttribute("name")] = inputNode + + elementNodes = self.inputRoot.getElementsByTagNameNS (self.inputNSAlias, "element") + for elementNode in elementNodes: + if not elementNode.hasAttribute("name") and not elementNode.hasAttribute("ref"): + self._addError ("Element must have 'name' or 'ref' attribute!", elementNode) + continue + + if elementNode.hasAttribute("name") and elementNode.hasAttribute("ref"): + self._addError ("Element must not have 'name' and 'ref' attribute!", elementNode) + continue + + if elementNode.hasAttribute("ref"): + elementRef = self.xmlIf.extractLocalName(elementNode.getAttribute("ref")) + if not self.inputElementDict.has_key(elementRef): + self._addError ("Reference to undefined element '%s'!" %(elementRef), elementNode) + + complexTypeNode = elementNode.getFirstChildNS (self.inputNSAlias, "complexType") + simpleTypeNode = elementNode.getFirstChildNS (self.inputNSAlias, "simpleType") + if elementNode.hasAttribute("type") and (complexTypeNode != None or simpleTypeNode != None): + self._addError ("Element has type attribute and type definition!", elementNode) + if not elementNode.hasAttribute("type") and complexTypeNode == None and simpleTypeNode == None: + self._addWarning ("Element has no type attribute and no type definition!", elementNode) + + minOccurs = elementNode.getAttributeOrDefault("minOccurs", "1") + maxOccurs = elementNode.getAttributeOrDefault("maxOccurs", "1") + if maxOccurs != "unbounded": + if string.atoi(minOccurs) > string.atoi(maxOccurs): + self._addError ("Attribute minOccurs > maxOccurs!", elementNode) + + + ######################################## + # additional checks for group nodes + # + def _checkGroupNodesSecondLevel(self): + self.inputGroupDict = {} + for groupNode in self.inputRoot.getChildrenNS(self.inputNSAlias, "group"): + self.inputGroupDict[groupNode.getAttribute("name")] = groupNode + + groupNodes = self.inputRoot.getElementsByTagNameNS (self.inputNSAlias, "group") + for groupNode in groupNodes: + if groupNode.hasAttribute("ref"): + groupRef = self.xmlIf.extractLocalName(groupNode.getAttribute("ref")) + if not self.inputGroupDict.has_key(groupRef): + self._addError ("Reference to undefined group '%s'!" %(groupRef), groupNode) + + + ######################################## + # additional checks for attributeGroup nodes + # + def _checkAttrGroupNodesSecondLevel(self): + self.inputAttrGroupDict = {} + for attrGroupNode in self.inputRoot.getChildrenNS(self.inputNSAlias, "attrGroup"): + self.inputAttrGroupDict[attrGroupNode.getAttribute("name")] = attrGroupNode + + attrGroupNodes = self.inputRoot.getElementsByTagNameNS (self.inputNSAlias, "attrGroup") + for attrGroupNode in attrGroupNodes: + if attrGroupNode.hasAttribute("ref"): + attrGroupRef = self.xmlIf.extractLocalName(attrGroupNode.getAttribute("ref")) + if not self.inputAttrGroupDict.has_key(attrGroupRef): + self._addError ("Reference to undefined attribute group '%s'!" %(attrGroupRef), attrGroupNode) + + + ######################################## + # additional checks for attribute nodes + # + def _checkAttributeNodesSecondLevel(self): + attributeNodes = self.inputRoot.getElementsByTagNameNS (self.inputNSAlias, "attribute") + for attributeNode in attributeNodes: + if not attributeNode.hasAttribute("name") and not attributeNode.hasAttribute("ref"): + self._addError ("Attribute must have 'name' or 'ref' attribute!", attributeNode) + continue + + if attributeNode.getAttribute("use") == "required" and attributeNode.hasAttribute("default"): + self._addError ("Attribute 'default' is not allowed, because 'use' is 'required'!", attributeNode) + elif attributeNode.hasAttribute("default") and attributeNode.hasAttribute("fixed"): + self._addError ("Attribute must not have 'default' AND 'fixed' attribute!", attributeNode) + + + ######################################## + # additional checks for simple types + # + def _checkSimpleTypesSecondLevel(self): + restrictionNodes, dummy = self.inputRoot.getXPathList (".//simpleType/restriction", self.inputNSAlias) + for restrictionNode in restrictionNodes: + if not restrictionNode.hasAttribute("base") and restrictionNode.getFirstChildNS (self.inputNSAlias, "simpleType") == None: + self._addError ("Simple type restriction must have 'base' attribute or 'simpleType' child tag!", restrictionNode) + + minExcl = restrictionNode.getFirstChildNS(self.inputNSAlias, "minExclusive") + minIncl = restrictionNode.getFirstChildNS(self.inputNSAlias, "minInclusive") + if minExcl != None and minIncl != None: + self._addError ("Restriction attributes 'minExclusive' and 'minInclusive' cannot be defined together!", restrictionNode) + maxExcl = restrictionNode.getFirstChildNS(self.inputNSAlias, "maxExclusive") + maxIncl = restrictionNode.getFirstChildNS(self.inputNSAlias, "maxInclusive") + if maxExcl != None and maxIncl != None: + self._addError ("Restriction attributes 'maxExclusive' and 'maxInclusive' cannot be defined together!", restrictionNode) + + listNodes = self.inputRoot.getElementsByTagNameNS (self.inputNSAlias, "list") + for listNode in listNodes: + if not listNode.hasAttribute("itemType") and restrictionNode.getFirstChildNS (self.inputNSAlias, "simpleType") == None: + self._addError ("List type must have 'itemType' attribute or 'simpleType' child tag!", listNode) + +