You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1281 lines
64 KiB
1281 lines
64 KiB
5 years ago
|
#
|
||
|
# minixsv, Release 0.9.0
|
||
|
# file: xsvalBase.py
|
||
|
#
|
||
|
# XML schema validator base class
|
||
|
#
|
||
|
# history:
|
||
|
# 2004-10-07 rl created
|
||
|
# 2006-08-18 rl W3C testsuite passed for supported features
|
||
|
# 2007-06-14 rl Features for release 0.8 added, several bugs fixed
|
||
|
#
|
||
|
# Copyright (c) 2004-2008 by Roland Leuthe. All rights reserved.
|
||
|
#
|
||
|
# --------------------------------------------------------------------
|
||
|
# The minixsv XML schema validator is
|
||
|
#
|
||
|
# Copyright (c) 2004-2008 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 string
|
||
|
import copy
|
||
|
from ..minixsv import *
|
||
|
from ..genxmlif.xmlifUtils import collapseString, convertToAbsUrl, NsNameTupleFactory, NsNameTuple
|
||
|
from xsvalSimpleTypes import XsSimpleTypeVal, SimpleTypeError
|
||
|
|
||
|
|
||
|
wxsdTree = None
|
||
|
wxsdLookupDict = {}
|
||
|
|
||
|
|
||
|
##########################################################
|
||
|
# Validator class for validating one input file against one XML schema file
|
||
|
|
||
|
class XsValBase:
|
||
|
|
||
|
def __init__(self, xmlIf, errorHandler, verbose):
|
||
|
self.xmlIf = xmlIf
|
||
|
self.errorHandler = errorHandler
|
||
|
self.verbose = verbose
|
||
|
|
||
|
self._raiseError = self.errorHandler.raiseError
|
||
|
self._addError = self.errorHandler.addError
|
||
|
self._addWarning = self.errorHandler.addWarning
|
||
|
self._addInfo = self.errorHandler.addInfo
|
||
|
|
||
|
self.checkKeyrefList = []
|
||
|
|
||
|
|
||
|
def unlink(self):
|
||
|
self.simpleTypeVal.unlink()
|
||
|
|
||
|
|
||
|
########################################
|
||
|
# validate inputTree against xsdTree
|
||
|
#
|
||
|
def validate (self, inputTree, xsdTreeList):
|
||
|
self.inputTree = inputTree
|
||
|
|
||
|
self.inputRoot = self.inputTree.getRootNode()
|
||
|
|
||
|
self.inputNsURI = self.inputRoot.getNamespaceURI()
|
||
|
self.inputNsPrefix = self.inputRoot.getNsPrefix(self.inputRoot.getNsName())
|
||
|
if self.inputNsPrefix != None:
|
||
|
self.inputNsPrefixString = "%s:" %(self.inputNsPrefix)
|
||
|
else:
|
||
|
self.inputNsPrefixString = ""
|
||
|
|
||
|
# initialise lookup dictionary
|
||
|
global wxsdLookupDict
|
||
|
if wxsdLookupDict == {}:
|
||
|
wxsdLookupDict = {"ElementDict":{}, "TypeDict":{}, "GroupDict":{},
|
||
|
"AttrGroupDict":{}, "AttributeDict":{}, "IdentityConstrDict":{}}
|
||
|
self._importWellknownSchemas(wxsdLookupDict)
|
||
|
|
||
|
self.xsdLookupDict = {"ElementDict": wxsdLookupDict["ElementDict"].copy(),
|
||
|
"TypeDict": wxsdLookupDict["TypeDict"].copy(),
|
||
|
"GroupDict": wxsdLookupDict["GroupDict"].copy(),
|
||
|
"AttrGroupDict": wxsdLookupDict["AttrGroupDict"].copy(),
|
||
|
"AttributeDict": wxsdLookupDict["AttributeDict"].copy(),
|
||
|
"IdentityConstrDict": wxsdLookupDict["IdentityConstrDict"].copy()}
|
||
|
self.xsdElementDict = self.xsdLookupDict["ElementDict"]
|
||
|
self.xsdTypeDict = self.xsdLookupDict["TypeDict"]
|
||
|
self.xsdGroupDict = self.xsdLookupDict["GroupDict"]
|
||
|
self.xsdAttrGroupDict = self.xsdLookupDict["AttrGroupDict"]
|
||
|
self.xsdAttributeDict = self.xsdLookupDict["AttributeDict"]
|
||
|
self.xsdIdentityConstrDict = self.xsdLookupDict["IdentityConstrDict"]
|
||
|
|
||
|
self.xsdIdDict = {}
|
||
|
self.xsdIdRefDict = {}
|
||
|
self.idAttributeForType = None
|
||
|
|
||
|
for xsdTree in xsdTreeList:
|
||
|
xsdRoot = xsdTree.getRootNode()
|
||
|
|
||
|
# TODO: The following member may differ if several schema files are used!!
|
||
|
self.xsdNsURI = xsdRoot.getNamespaceURI()
|
||
|
|
||
|
self.xsdIncludeDict = {xsdRoot.getAbsUrl():1,}
|
||
|
if xsdRoot.getFilePath() != os.path.join (MINIXSV_DIR, "XMLSchema.xsd"):
|
||
|
self._initInternalAttributes (xsdRoot)
|
||
|
self._updateLookupTables(xsdRoot, self.xsdLookupDict)
|
||
|
|
||
|
self._includeAndImport (xsdTree, xsdTree, self.xsdIncludeDict, self.xsdLookupDict)
|
||
|
|
||
|
|
||
|
self.simpleTypeVal = XsSimpleTypeVal(self)
|
||
|
|
||
|
inputRootNsName = self.inputRoot.getNsName()
|
||
|
if self.xsdElementDict.has_key(inputRootNsName):
|
||
|
# start recursive schema validation
|
||
|
try:
|
||
|
self._checkElementTag (self.xsdElementDict[inputRootNsName], self.inputRoot, (self.inputRoot,), 0)
|
||
|
except TagException, errInst:
|
||
|
self._addError (errInst.errstr, errInst.node, errInst.endTag)
|
||
|
|
||
|
if not self.errorHandler.hasErrors():
|
||
|
# validate IDREFs
|
||
|
for idref in self.xsdIdRefDict.keys():
|
||
|
if not self.xsdIdDict.has_key(idref):
|
||
|
self._addError ("There is no ID/IDREF binding for IDREF %s" %repr(idref), self.xsdIdRefDict[idref])
|
||
|
|
||
|
# validate keyrefs
|
||
|
for inputElement, keyrefNode in self.checkKeyrefList:
|
||
|
self._checkKeyRefConstraint (keyrefNode, inputElement)
|
||
|
else:
|
||
|
self._raiseError ("Used root tag %s not found in schema file(s)!"
|
||
|
%repr(inputRootNsName), self.inputRoot)
|
||
|
|
||
|
|
||
|
########################################
|
||
|
# include/import all files specified in the schema file
|
||
|
# import well-known schemas
|
||
|
#
|
||
|
def _includeAndImport (self, baseTree, tree, includeDict, lookupDict):
|
||
|
self._expandIncludes (baseTree, tree, includeDict, lookupDict)
|
||
|
self._expandRedefines (baseTree, tree, includeDict, lookupDict)
|
||
|
self._expandImports (baseTree, tree, includeDict, lookupDict)
|
||
|
|
||
|
|
||
|
########################################
|
||
|
# expand include directives
|
||
|
#
|
||
|
def _expandIncludes (self, baseTree, tree, includeDict, lookupDict):
|
||
|
rootNode = tree.getRootNode()
|
||
|
namespaceURI = rootNode.getNamespaceURI()
|
||
|
for includeNode in rootNode.getChildrenNS(namespaceURI, "include"):
|
||
|
includeUrl = includeNode.getAttribute("schemaLocation")
|
||
|
expNamespace = rootNode.getAttributeOrDefault("targetNamespace", None)
|
||
|
self._includeSchemaFile (baseTree, tree, includeNode, expNamespace, includeUrl, includeNode.getBaseUrl(), includeDict, lookupDict,
|
||
|
adaptTargetNamespace=1)
|
||
|
rootNode.removeChild (includeNode)
|
||
|
|
||
|
|
||
|
########################################
|
||
|
# expand redefine directives
|
||
|
#
|
||
|
def _expandRedefines (self, baseTree, tree, includeDict, lookupDict):
|
||
|
rootNode = tree.getRootNode()
|
||
|
namespaceURI = rootNode.getNamespaceURI()
|
||
|
|
||
|
for redefineNode in rootNode.getChildrenNS(namespaceURI, "redefine"):
|
||
|
redefineUrl = redefineNode.getAttribute("schemaLocation")
|
||
|
expNamespace = rootNode.getAttributeOrDefault("targetNamespace", None)
|
||
|
self._includeSchemaFile (baseTree, tree, redefineNode, expNamespace, redefineUrl, redefineNode.getBaseUrl(), includeDict, lookupDict,
|
||
|
adaptTargetNamespace=1)
|
||
|
|
||
|
# fill lookup tables with redefined definitions
|
||
|
for childNode in redefineNode.getChildren():
|
||
|
redefineNode.removeChild(childNode)
|
||
|
rootNode.insertBefore(childNode, redefineNode)
|
||
|
|
||
|
if childNode.getLocalName() in ("complexType", "simpleType"):
|
||
|
xsdDict = self.xsdLookupDict["TypeDict"]
|
||
|
elif childNode.getLocalName() in ("attributeGroup"):
|
||
|
xsdDict = self.xsdLookupDict["AttrGroupDict"]
|
||
|
elif childNode.getLocalName() in ("group"):
|
||
|
xsdDict = self.xsdLookupDict["GroupDict"]
|
||
|
elif childNode.getLocalName() in ("annotation"):
|
||
|
continue
|
||
|
else:
|
||
|
self._addError ("%s not allowed as child of 'redefine'!" %repr(childNode.getLocalName()), childNode)
|
||
|
continue
|
||
|
|
||
|
redefType = NsNameTuple ( (expNamespace, childNode.getAttribute("name")) )
|
||
|
if xsdDict.has_key(redefType):
|
||
|
orgRedefType = NsNameTuple( (expNamespace, redefType[1]+"__ORG") )
|
||
|
if not xsdDict.has_key(orgRedefType):
|
||
|
xsdDict[orgRedefType] = xsdDict[redefType]
|
||
|
# else:
|
||
|
# self._addError ("Duplicate component %s found within 'redefine'!" %repr(redefType), childNode)
|
||
|
xsdDict[redefType] = childNode
|
||
|
else:
|
||
|
self._addError ("Type %s not found in imported schema file!" %(repr(redefType)), childNode)
|
||
|
|
||
|
dummy, attrNodes, attrNsNameFirst = childNode.getXPathList (".//@base | .//@ref" % vars())
|
||
|
for attrNode in attrNodes:
|
||
|
if attrNode.hasAttribute("base"):
|
||
|
attribute = "base"
|
||
|
elif attrNode.hasAttribute("ref"):
|
||
|
attribute = "ref"
|
||
|
if attrNode.getQNameAttribute(attribute) == redefType:
|
||
|
attrNode[attribute] = attrNode[attribute] + "__ORG"
|
||
|
|
||
|
rootNode.removeChild (redefineNode)
|
||
|
|
||
|
|
||
|
########################################
|
||
|
# expand import directives
|
||
|
#
|
||
|
def _expandImports (self, baseTree, tree, includeDict, lookupDict):
|
||
|
rootNode = tree.getRootNode()
|
||
|
namespaceURI = rootNode.getNamespaceURI()
|
||
|
|
||
|
for includeNode in rootNode.getChildrenNS(namespaceURI, "import"):
|
||
|
expNamespace = includeNode.getAttributeOrDefault("namespace", None)
|
||
|
if expNamespace == self._getTargetNamespace(includeNode):
|
||
|
self._addError ("Target namespace and target namespace of imported schema must not be the same!", includeNode)
|
||
|
continue
|
||
|
|
||
|
includeUrl = includeNode.getAttributeOrDefault("schemaLocation", None)
|
||
|
if expNamespace != None and includeUrl == None:
|
||
|
includeUrl = expNamespace + ".xsd"
|
||
|
if includeUrl != None:
|
||
|
if expNamespace not in (XML_NAMESPACE, XSI_NAMESPACE):
|
||
|
self._includeSchemaFile (baseTree, tree, includeNode, expNamespace, includeUrl, includeNode.getBaseUrl(), includeDict, lookupDict)
|
||
|
else:
|
||
|
self._addError ("schemaLocation attribute for import directive missing!", includeNode)
|
||
|
rootNode.removeChild (includeNode)
|
||
|
|
||
|
|
||
|
########################################
|
||
|
# import well-known schema files
|
||
|
#
|
||
|
def _importWellknownSchemas (self, lookupDict):
|
||
|
global wxsdTree
|
||
|
file = os.path.join (MINIXSV_DIR, "XMLSchema.xsd")
|
||
|
wxsdTree = self.xmlIf.parse (file)
|
||
|
self._initInternalAttributes (wxsdTree.getRootNode())
|
||
|
self._updateLookupTables (wxsdTree.getRootNode(), lookupDict)
|
||
|
|
||
|
for schemaFile in ("datatypes.xsd", "xml.xsd", "XMLSchema-instance.xsd"):
|
||
|
file = os.path.join (MINIXSV_DIR, schemaFile)
|
||
|
subTree = self._parseIncludeSchemaFile(wxsdTree, wxsdTree, None, file, None)
|
||
|
self._updateLookupTables (subTree.getRootNode(), lookupDict)
|
||
|
|
||
|
|
||
|
########################################
|
||
|
# include/import a schema file
|
||
|
#
|
||
|
def _includeSchemaFile (self, baseTree, tree, nextSibling, expNamespace, includeUrl, baseUrl, includeDict, lookupDict,
|
||
|
adaptTargetNamespace=0):
|
||
|
if includeUrl == None:
|
||
|
self._raiseError ("Schema location attribute missing!", nextSibling)
|
||
|
absUrl = convertToAbsUrl (includeUrl, baseUrl)
|
||
|
if includeDict.has_key (absUrl):
|
||
|
# file already included
|
||
|
return
|
||
|
|
||
|
if self.verbose:
|
||
|
print "including %s..." %(includeUrl)
|
||
|
rootNode = tree.getRootNode()
|
||
|
|
||
|
subTree = self._parseIncludeSchemaFile(baseTree, tree, nextSibling, includeUrl, baseUrl)
|
||
|
includeDict[absUrl] = 1
|
||
|
|
||
|
stRootNode = subTree.getRootNode()
|
||
|
if rootNode.getNsName() != stRootNode.getNsName():
|
||
|
self._raiseError ("Root tag of file %s does not match!" %repr(includeUrl), nextSibling)
|
||
|
|
||
|
if stRootNode.hasAttribute("targetNamespace"):
|
||
|
if expNamespace != stRootNode["targetNamespace"]:
|
||
|
self._raiseError ("Target namespace of file %s does not match!" %repr(includeUrl), nextSibling)
|
||
|
else:
|
||
|
if expNamespace != None:
|
||
|
if adaptTargetNamespace:
|
||
|
# if no target namespace is specified in the included file
|
||
|
# the target namespace of the parent file is taken
|
||
|
stRootNode["targetNamespace"] = expNamespace
|
||
|
for stDescNode in stRootNode.getIterator():
|
||
|
stDescNode.curNs.append((EMPTY_PREFIX,expNamespace))
|
||
|
else:
|
||
|
self._raiseError ("Target namespace of file %s does not match!" %repr(includeUrl), nextSibling)
|
||
|
|
||
|
self._updateLookupTables (subTree.getRootNode(), lookupDict)
|
||
|
self._includeAndImport (baseTree, subTree, includeDict, lookupDict)
|
||
|
if includeUrl not in (r"C:\Program Files\Python24\Lib\site-packages\minixsv\xml.xsd",
|
||
|
r"C:\Program Files\Python24\Lib\site-packages\minixsv\XMLSchema.xsd",
|
||
|
r"C:\Program Files\Python24\Lib\site-packages\minixsv\XMLSchema-instance.xsd"):
|
||
|
rootNode.insertSubtree (nextSibling, subTree, insertSubTreeRootNode=0)
|
||
|
|
||
|
|
||
|
def _parseIncludeSchemaFile (self, baseTree, tree, nextSibling, includeUrl, baseUrl):
|
||
|
# try to parse included schema file
|
||
|
try:
|
||
|
subTree = self.xmlIf.parse (includeUrl, baseUrl, baseTree.getTree())
|
||
|
self._initInternalAttributes (subTree.getRootNode())
|
||
|
except IOError, errInst:
|
||
|
self._raiseError ("%s" %str(errInst), nextSibling)
|
||
|
except SyntaxError, e:
|
||
|
# FIXME: sometimes an URLError is catched instead of a standard IOError
|
||
|
try:
|
||
|
dummy = e.errno
|
||
|
except:
|
||
|
raise IOError, e
|
||
|
|
||
|
if e.errno in (2, "socket error", "url error"): # catch IOError: No such file or directory
|
||
|
self._raiseError ("%s: '%s'" %(e.strerror, e.filename), nextSibling)
|
||
|
else:
|
||
|
raise
|
||
|
|
||
|
return subTree
|
||
|
|
||
|
########################################
|
||
|
# update lookup dictionaries used during validation
|
||
|
#
|
||
|
def _updateLookupTables (self, rootNode, lookupDict):
|
||
|
schemaTagDict = {"element" : "ElementDict",
|
||
|
"complexType": "TypeDict",
|
||
|
"simpleType" : "TypeDict",
|
||
|
"group" : "GroupDict",
|
||
|
"attributeGroup": "AttrGroupDict",
|
||
|
"attribute" : "AttributeDict",
|
||
|
}
|
||
|
|
||
|
# retrieve all schema tags
|
||
|
for localName, lookupDictName in schemaTagDict.items():
|
||
|
for node in rootNode.getChildrenNS(XSD_NAMESPACE, localName):
|
||
|
targetNamespace = self._getTargetNamespace(node)
|
||
|
if not lookupDict[lookupDictName].has_key((targetNamespace, node.getAttribute("name"))):
|
||
|
lookupDict[lookupDictName][(targetNamespace, node.getAttribute("name"))] = node
|
||
|
|
||
|
# retrieve all identity constraints
|
||
|
for identConstrTagName in ("unique", "key", "keyref"):
|
||
|
identConstrNodeList = rootNode.getElementsByTagNameNS (XSD_NAMESPACE, identConstrTagName)
|
||
|
for identConstrNode in identConstrNodeList:
|
||
|
targetNamespace = self._getTargetNamespace(identConstrNode)
|
||
|
identConstrNsLocalName = NsNameTupleFactory ( (targetNamespace, identConstrNode.getAttribute("name")) )
|
||
|
if not lookupDict["IdentityConstrDict"].has_key(identConstrNsLocalName):
|
||
|
lookupDict["IdentityConstrDict"][identConstrNsLocalName] = {"Node": identConstrNode, "ValueDict":{}}
|
||
|
|
||
|
# else:
|
||
|
# self._addError ("Duplicate identity constraint name %s found!"
|
||
|
# %(repr(identConstrNsLocalName)), identConstrNode)
|
||
|
|
||
|
########################################
|
||
|
# validate inputNode against complexType node
|
||
|
#
|
||
|
def _initInternalAttributes (self, rootNode):
|
||
|
# set schema root node for all descendant nodes
|
||
|
if not rootNode.getSchemaRootNode():
|
||
|
for node in rootNode.getIterator():
|
||
|
node.setSchemaRootNode(rootNode)
|
||
|
|
||
|
|
||
|
########################################
|
||
|
# validate inputNode against complexType node
|
||
|
#
|
||
|
def _checkComplexTypeTag (self, xsdParentNode, xsdNode, inputNode, inputChildIndex, usedAsBaseType=None):
|
||
|
baseTypeAttributes = {}
|
||
|
|
||
|
complexContentNode = xsdNode.getFirstChildNS(self.xsdNsURI, "complexContent")
|
||
|
simpleContentNode = xsdNode.getFirstChildNS(self.xsdNsURI, "simpleContent")
|
||
|
if complexContentNode != None:
|
||
|
inputChildIndex, baseTypeAttributes = self._checkComplexContentTag (xsdParentNode, complexContentNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes)
|
||
|
elif simpleContentNode != None:
|
||
|
inputChildIndex, baseTypeAttributes = self._checkSimpleContentTag (xsdParentNode, simpleContentNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes)
|
||
|
else:
|
||
|
inputChildIndex, baseTypeAttributes = self._checkComplexTypeContent (xsdParentNode, xsdNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes)
|
||
|
if usedAsBaseType == None:
|
||
|
self._checkMixed (xsdParentNode, xsdNode, inputNode)
|
||
|
return inputChildIndex, baseTypeAttributes
|
||
|
|
||
|
def _checkComplexContentTag (self, xsdParentNode, xsdNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes):
|
||
|
extensionNode = xsdNode.getFirstChildNS(self.xsdNsURI, "extension")
|
||
|
if extensionNode != None:
|
||
|
inputChildIndex, baseTypeAttributes = self._checkExtensionComplexContent (xsdParentNode, extensionNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes)
|
||
|
else:
|
||
|
restrictionNode = xsdNode.getFirstChildNS(self.xsdNsURI, "restriction")
|
||
|
if restrictionNode != None:
|
||
|
inputChildIndex, baseTypeAttributes = self._checkRestrictionComplexContent (xsdParentNode, restrictionNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes)
|
||
|
else:
|
||
|
raise AttributeError, "RestrictionNode not found!"
|
||
|
|
||
|
# if usedAsBaseType == None:
|
||
|
# self._checkMixed (xsdNode, inputNode)
|
||
|
return inputChildIndex, baseTypeAttributes
|
||
|
|
||
|
def _checkSimpleContentTag (self, xsdParentNode, xsdNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes):
|
||
|
if inputNode.getAttribute( (XSI_NAMESPACE, "nil") ) == "true":
|
||
|
if inputNode.getChildren() != [] or collapseString(inputNode.getElementValue()) != "":
|
||
|
self._addError ("Element must be empty (xsi:nil='true')(1)!" , inputNode, 0)
|
||
|
|
||
|
extensionNode = xsdNode.getFirstChildNS(self.xsdNsURI, "extension")
|
||
|
if extensionNode != None:
|
||
|
inputChildIndex, baseTypeAttributes = self._checkExtensionSimpleContent (xsdParentNode, extensionNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes)
|
||
|
else:
|
||
|
restrictionNode = xsdNode.getFirstChildNS(self.xsdNsURI, "restriction")
|
||
|
if restrictionNode != None:
|
||
|
inputChildIndex, baseTypeAttributes = self._checkRestrictionSimpleContent (xsdParentNode, xsdNode, restrictionNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes)
|
||
|
return inputChildIndex, baseTypeAttributes
|
||
|
|
||
|
def _checkExtensionComplexContent (self, xsdParentNode, xsdNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes):
|
||
|
baseNsName = xsdNode.getQNameAttribute("base")
|
||
|
if usedAsBaseType == None:
|
||
|
extUsedAsBaseType = "extension"
|
||
|
else:
|
||
|
extUsedAsBaseType = usedAsBaseType
|
||
|
inputChildIndex, baseTypeAttributes = self._checkComplexTypeTag (xsdParentNode, self.xsdTypeDict[baseNsName], inputNode, inputChildIndex, extUsedAsBaseType)
|
||
|
|
||
|
inputChildIndex, baseTypeAttributes = self._checkComplexTypeContent (xsdParentNode, xsdNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes)
|
||
|
return inputChildIndex, baseTypeAttributes
|
||
|
|
||
|
def _checkExtensionSimpleContent (self, xsdParentNode, xsdNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes):
|
||
|
self._checkSimpleType (xsdNode, "base", inputNode, inputNode.getTagName(), inputNode.getElementValue(), None, checkAttribute=0)
|
||
|
if xsdNode.hasAttribute("BaseTypes"):
|
||
|
xsdParentNode["BaseTypes"] = xsdNode["BaseTypes"]
|
||
|
inputChildIndex, baseTypeAttributes = self._checkSimpleTypeContent (xsdParentNode, xsdNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes)
|
||
|
return inputChildIndex, baseTypeAttributes
|
||
|
|
||
|
def _checkRestrictionComplexContent (self, xsdParentNode, xsdNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes):
|
||
|
# first check against base type (retrieve only the base type attributes)
|
||
|
baseNsName = xsdNode.getQNameAttribute("base")
|
||
|
inputChildIndex, baseTypeAttributes = self._checkComplexTypeTag (xsdParentNode, self.xsdTypeDict[baseNsName], inputNode, inputChildIndex, "restriction")
|
||
|
|
||
|
# then check input against derived complex type
|
||
|
inputChildIndex, baseTypeAttributes = self._checkComplexTypeContent (xsdParentNode, xsdNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes)
|
||
|
return inputChildIndex, baseTypeAttributes
|
||
|
|
||
|
def _checkRestrictionSimpleContent (self, xsdParentNode, simpleContentNode, xsdNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes):
|
||
|
try:
|
||
|
simpleTypeReturnDict = {"BaseTypes":[], "primitiveType":None}
|
||
|
self.simpleTypeVal.checkSimpleTypeDef (inputNode, simpleContentNode, inputNode.getTagName(), inputNode.getElementValue(), simpleTypeReturnDict, idCheck=1)
|
||
|
xsdNode["BaseTypes"] = string.join (simpleTypeReturnDict["BaseTypes"], " ")
|
||
|
except SimpleTypeError, errInst:
|
||
|
self._addError (errInst.args[0], inputNode)
|
||
|
|
||
|
inputChildIndex, baseTypeAttributes = self._checkSimpleTypeContent (xsdParentNode, xsdNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes)
|
||
|
return inputChildIndex, baseTypeAttributes
|
||
|
|
||
|
def _checkComplexTypeContent (self, xsdParentNode, xsdNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes):
|
||
|
if inputNode.getAttribute((XSI_NAMESPACE, "nil")) == "true":
|
||
|
if inputNode.getChildren() != [] or collapseString(inputNode.getElementValue()) != "":
|
||
|
self._addError ("Element must be empty (xsi:nil='true')(2)!" , inputNode, 0)
|
||
|
else:
|
||
|
childTags = inputNode.getChildren()
|
||
|
if usedAsBaseType in (None, "extension"):
|
||
|
validChildTags = xsdNode.getChildren()
|
||
|
for validChildTag in validChildTags:
|
||
|
if validChildTag.getLocalName() not in ("attribute", "attributeGroup", "anyAttribute"):
|
||
|
inputChildIndex = self._checkParticle (validChildTag, inputNode, childTags, inputChildIndex)
|
||
|
|
||
|
if usedAsBaseType == None and inputChildIndex < len (childTags):
|
||
|
inputNsName = inputNode.getNsName()
|
||
|
childNsName = childTags[inputChildIndex].getNsName()
|
||
|
self._addError ("Unexpected or invalid child tag %s found in tag %s!"
|
||
|
%(repr(childNsName), repr(inputNsName)), childTags[inputChildIndex])
|
||
|
|
||
|
if usedAsBaseType in (None,):
|
||
|
self._checkAttributeTags (xsdParentNode, xsdNode, inputNode, baseTypeAttributes)
|
||
|
|
||
|
if usedAsBaseType in ("restriction", "extension"):
|
||
|
self._updateAttributeDict (xsdNode, baseTypeAttributes)
|
||
|
|
||
|
return inputChildIndex, baseTypeAttributes
|
||
|
|
||
|
def _checkSimpleTypeContent (self, xsdParentNode, xsdNode, inputNode, inputChildIndex, usedAsBaseType, baseTypeAttributes):
|
||
|
if inputNode.getChildren() != []:
|
||
|
raise TagException ("No child tags are allowed for element %s!" %repr(inputNode.getNsName()), inputNode)
|
||
|
|
||
|
if usedAsBaseType in (None,):
|
||
|
self._checkAttributeTags (xsdParentNode, xsdNode, inputNode, baseTypeAttributes)
|
||
|
|
||
|
if usedAsBaseType in ("restriction", "extension"):
|
||
|
self._updateAttributeDict (xsdNode, baseTypeAttributes)
|
||
|
|
||
|
return inputChildIndex, baseTypeAttributes
|
||
|
|
||
|
|
||
|
########################################
|
||
|
# validate mixed content (1)
|
||
|
#
|
||
|
def _checkMixed (self, xsdParentNode, xsdNode, inputNode):
|
||
|
if xsdNode.getAttributeOrDefault ("mixed", "false") == "false":
|
||
|
if not collapseString(inputNode.getElementValue()) in ("", " "):
|
||
|
self._addError ("Mixed content not allowed for %s!" %repr(inputNode.getTagName()), inputNode)
|
||
|
else: # mixed = true
|
||
|
self._checkUrType(xsdParentNode, inputNode)
|
||
|
|
||
|
|
||
|
########################################
|
||
|
# check ur-type
|
||
|
#
|
||
|
def _checkUrType (self, xsdNode, inputNode):
|
||
|
prefix = xsdNode.getPrefix()
|
||
|
if prefix:
|
||
|
xsdNode["__CONTENTTYPE__"] = "%s:string" %xsdNode.getPrefix()
|
||
|
else:
|
||
|
xsdNode["__CONTENTTYPE__"] = "string"
|
||
|
self._checkElementValue (xsdNode, "__CONTENTTYPE__", inputNode)
|
||
|
xsdNode.removeAttribute("__CONTENTTYPE__")
|
||
|
|
||
|
|
||
|
########################################
|
||
|
# validate inputNodeList against xsdNode
|
||
|
#
|
||
|
def _checkList (self, elementMethod, xsdNode, inputParentNode, inputNodeList, currIndex):
|
||
|
minOccurs = string.atoi(xsdNode.getAttributeOrDefault("minOccurs", "1"))
|
||
|
maxOccurs = xsdNode.getAttributeOrDefault("maxOccurs", "1")
|
||
|
if maxOccurs != "unbounded":
|
||
|
maxOccurs = string.atoi(maxOccurs)
|
||
|
else:
|
||
|
maxOccurs = -1
|
||
|
occurs = 0
|
||
|
while maxOccurs == -1 or occurs < maxOccurs:
|
||
|
try:
|
||
|
newIndex = elementMethod (xsdNode, inputParentNode, inputNodeList, currIndex)
|
||
|
occurs += 1
|
||
|
if newIndex > currIndex:
|
||
|
currIndex = newIndex
|
||
|
else:
|
||
|
break # no suitable element found
|
||
|
except TagException, errInst:
|
||
|
break
|
||
|
|
||
|
if occurs == 0 and minOccurs > 0:
|
||
|
raise errInst
|
||
|
elif occurs < minOccurs:
|
||
|
expInputTagName = xsdNode.getAttribute("name")
|
||
|
if expInputTagName == None:
|
||
|
expInputTagName = xsdNode.getQNameAttribute("ref")
|
||
|
raise TagException ("minOccurs (%d) of child tag %s in tag %s not available (only %d)!"
|
||
|
%(minOccurs, repr(expInputTagName), repr(inputParentNode.getTagName()), occurs), inputParentNode, 1)
|
||
|
|
||
|
return currIndex
|
||
|
|
||
|
########################################
|
||
|
# validate inputNode against element node
|
||
|
#
|
||
|
def _checkElementTag (self, xsdNode, inputParentNode, inputNodeList, currIndex):
|
||
|
if xsdNode.hasAttribute("ref"):
|
||
|
refNsName = xsdNode.getQNameAttribute("ref")
|
||
|
currIndex = self._checkElementTag (self.xsdElementDict[refNsName], inputParentNode, inputNodeList, currIndex)
|
||
|
else:
|
||
|
nameAttr = xsdNode.getAttribute ("name")
|
||
|
|
||
|
if currIndex >= len (inputNodeList):
|
||
|
raise TagException ("Missing child tag %s in tag %s!" %(repr(nameAttr), repr(inputParentNode.getTagName())), inputParentNode, 1)
|
||
|
|
||
|
inputNode = inputNodeList[currIndex]
|
||
|
if nameAttr != inputNode.getLocalName():
|
||
|
raise TagException ("Missing child tag %s in tag %s!" %(repr(nameAttr), repr(inputParentNode.getTagName())), inputNode, 0)
|
||
|
|
||
|
# store reference to XSD definition node
|
||
|
inputNode.setXsdNode(xsdNode)
|
||
|
|
||
|
currIndex = currIndex + 1
|
||
|
|
||
|
self._checkInputElementForm (xsdNode, nameAttr, inputNode)
|
||
|
|
||
|
if (xsdNode.getFirstChild() == None and
|
||
|
not xsdNode.hasAttribute("type") and
|
||
|
not inputNode.hasAttribute((XSI_NAMESPACE, "type")) ):
|
||
|
self._checkUrType(xsdNode, inputNode)
|
||
|
# ur-type => try to check children of input node
|
||
|
for inputChild in inputNode.getChildren():
|
||
|
try:
|
||
|
if self.xsdElementDict.has_key(inputChild.getNsName()):
|
||
|
self._checkElementTag (self.xsdElementDict[inputChild.getNsName()], inputNode, (inputChild,), 0)
|
||
|
except TagException, errInst:
|
||
|
self._addError (errInst.errstr, errInst.node, errInst.endTag)
|
||
|
return currIndex
|
||
|
|
||
|
complexTypeNode = xsdNode.getFirstChildNS (self.xsdNsURI, "complexType")
|
||
|
if not inputNode.hasAttribute((XSI_NAMESPACE, "type")):
|
||
|
typeNsName = xsdNode.getQNameAttribute ("type")
|
||
|
else:
|
||
|
# overloaded type is used
|
||
|
typeNsName = inputNode.getQNameAttribute((XSI_NAMESPACE, "type"))
|
||
|
if not self.xsdTypeDict.has_key(typeNsName):
|
||
|
self._addError ("Unknown overloaded type %s!" %(repr(typeNsName)), inputNode, 0)
|
||
|
return currIndex
|
||
|
|
||
|
if self.xsdTypeDict.has_key (typeNsName):
|
||
|
typeType = self.xsdTypeDict[typeNsName].getLocalName()
|
||
|
if typeType == "complexType":
|
||
|
complexTypeNode = self.xsdTypeDict[typeNsName]
|
||
|
# else simpleType => pass, handled later on
|
||
|
|
||
|
if complexTypeNode != None:
|
||
|
try:
|
||
|
self._checkComplexTypeTag (xsdNode, complexTypeNode, inputNode, 0)
|
||
|
except TagException, errInst:
|
||
|
self._addError (errInst.errstr, errInst.node, errInst.endTag)
|
||
|
return currIndex
|
||
|
else:
|
||
|
self._checkElementSimpleType (xsdNode, "type", inputNode)
|
||
|
|
||
|
# check unique attributes and keys
|
||
|
childUniqueDefList = xsdNode.getChildrenNS (self.xsdNsURI, "unique")
|
||
|
for childUniqueDef in childUniqueDefList:
|
||
|
self._checkIdentityConstraint (childUniqueDef, inputNode)
|
||
|
|
||
|
childKeyDefList = xsdNode.getChildrenNS (self.xsdNsURI, "key")
|
||
|
for childKeyDef in childKeyDefList:
|
||
|
self._checkIdentityConstraint (childKeyDef, inputNode)
|
||
|
|
||
|
childKeyrefDefList = xsdNode.getChildrenNS (self.xsdNsURI, "keyref")
|
||
|
for childKeyrefDef in childKeyrefDefList:
|
||
|
self.checkKeyrefList.append ((inputNode, childKeyrefDef))
|
||
|
|
||
|
return currIndex
|
||
|
|
||
|
|
||
|
########################################
|
||
|
# validate element inputNode against simple type definition
|
||
|
#
|
||
|
def _checkElementSimpleType (self, xsdNode, xsdTypeAttr, inputNode):
|
||
|
if inputNode.getChildren() != []:
|
||
|
raise TagException ("No child tags are allowed for element %s!" %(repr(inputNode.getNsName())), inputNode)
|
||
|
|
||
|
self._checkElementValue (xsdNode, xsdTypeAttr, inputNode)
|
||
|
|
||
|
self._checkAttributeTags (xsdNode, xsdNode, inputNode, {})
|
||
|
|
||
|
|
||
|
########################################
|
||
|
# validate inputNode against simple type definition
|
||
|
#
|
||
|
def _checkElementValue (self, xsdNode, xsdTypeAttr, inputNode):
|
||
|
fixedValue = xsdNode.getAttribute("fixed")
|
||
|
if inputNode.getAttribute((XSI_NAMESPACE, "nil")) == "true" and fixedValue != None:
|
||
|
self._addError ("There must be no fixed value for Element because xsi:nil='true' is specified!" , inputNode)
|
||
|
|
||
|
if inputNode.getAttribute((XSI_NAMESPACE, "nil")) != "true" and inputNode.getElementValue() == "":
|
||
|
if xsdNode.hasAttribute("default"):
|
||
|
inputNode.setElementValue(xsdNode["default"])
|
||
|
if fixedValue != None:
|
||
|
inputNode.setElementValue(fixedValue)
|
||
|
|
||
|
self._checkSimpleType (xsdNode, xsdTypeAttr, inputNode, inputNode.getTagName(), inputNode.getElementValue(), fixedValue, checkAttribute=0)
|
||
|
|
||
|
|
||
|
########################################
|
||
|
# validate inputNode against simple type definition
|
||
|
#
|
||
|
def _checkSimpleType (self, xsdNode, xsdTypeAttr, inputNode, attrName, attrValue, fixedValue, checkAttribute=0, checkId=1):
|
||
|
retValue = None
|
||
|
|
||
|
if checkAttribute == 0 and inputNode.hasAttribute((XSI_NAMESPACE, "nil")):
|
||
|
if (inputNode[(XSI_NAMESPACE, "nil")] == "true" and
|
||
|
collapseString(inputNode.getElementValue()) != ""):
|
||
|
self._addError ("Element must be empty (xsi:nil='true')(3)!" , inputNode, 0)
|
||
|
return retValue
|
||
|
|
||
|
try:
|
||
|
simpleTypeReturnDict = {"BaseTypes":[], "primitiveType":None}
|
||
|
fixedValueReturnDict = {"BaseTypes":[], "primitiveType":None}
|
||
|
simpleTypeNode = xsdNode.getFirstChildNS (self.xsdNsURI, "simpleType")
|
||
|
if simpleTypeNode != None:
|
||
|
self.simpleTypeVal.checkSimpleTypeDef (inputNode, simpleTypeNode, attrName, attrValue, simpleTypeReturnDict, checkId)
|
||
|
if fixedValue != None:
|
||
|
self.simpleTypeVal.checkSimpleTypeDef (inputNode, simpleTypeNode, attrName, fixedValue, fixedValueReturnDict, idCheck=0)
|
||
|
elif (xsdNode.getFirstChildNS (self.xsdNsURI, "complexType") != None and
|
||
|
xsdNode.getFirstChildNS (self.xsdNsURI, "complexType").getAttribute("mixed") == "false"):
|
||
|
self._addError ("Attribute %s requires a simple or mixed type!" %repr(attrName), inputNode)
|
||
|
else:
|
||
|
typeNsName = xsdNode.getQNameAttribute (xsdTypeAttr)
|
||
|
if typeNsName != (None, None):
|
||
|
self.simpleTypeVal.checkSimpleType (inputNode, attrName, typeNsName, attrValue, simpleTypeReturnDict, checkId)
|
||
|
# TODO: What to check if no type is specified for the element?
|
||
|
if fixedValue != None:
|
||
|
self.simpleTypeVal.checkSimpleType (inputNode, attrName, typeNsName, fixedValue, fixedValueReturnDict, idCheck=0)
|
||
|
|
||
|
xsdNode["BaseTypes"] = string.join (simpleTypeReturnDict["BaseTypes"], " ")
|
||
|
xsdNode["primitiveType"] = str(simpleTypeReturnDict["primitiveType"])
|
||
|
|
||
|
retValue = simpleTypeReturnDict
|
||
|
if simpleTypeReturnDict.has_key("wsAction"):
|
||
|
if checkAttribute:
|
||
|
attrValue = inputNode.processWsAttribute(attrName, simpleTypeReturnDict["wsAction"])
|
||
|
else:
|
||
|
attrValue = inputNode.processWsElementValue(simpleTypeReturnDict["wsAction"])
|
||
|
|
||
|
if fixedValue != None:
|
||
|
if fixedValueReturnDict.has_key("orderedValue"):
|
||
|
fixedValue = fixedValueReturnDict["orderedValue"]
|
||
|
elif fixedValueReturnDict.has_key("adaptedAttrValue"):
|
||
|
fixedValue = fixedValueReturnDict["adaptedAttrValue"]
|
||
|
if simpleTypeReturnDict.has_key("orderedValue"):
|
||
|
attrValue = simpleTypeReturnDict["orderedValue"]
|
||
|
if attrValue != fixedValue:
|
||
|
if checkAttribute:
|
||
|
self._addError ("Attribute %s must have fixed value %s!" %(repr(attrName), repr(fixedValue)), inputNode)
|
||
|
else:
|
||
|
self._addError ("Element must have fixed value %s!" %repr(fixedValue), inputNode)
|
||
|
|
||
|
except SimpleTypeError, errInst:
|
||
|
self._addError (errInst.args[0], inputNode)
|
||
|
|
||
|
return retValue
|
||
|
|
||
|
########################################
|
||
|
# validate inputNode against sequence node
|
||
|
#
|
||
|
def _checkSequenceTag (self, xsdNode, inputParentNode, inputNodeList, currIndex):
|
||
|
for xsdChildNode in xsdNode.getChildren():
|
||
|
currIndex = self._checkParticle (xsdChildNode, inputParentNode, inputNodeList, currIndex)
|
||
|
return currIndex
|
||
|
|
||
|
|
||
|
########################################
|
||
|
# validate inputNode against choice node
|
||
|
#
|
||
|
def _checkChoiceTag (self, xsdNode, inputParentNode, inputNodeList, currIndex):
|
||
|
childFound = 0
|
||
|
exceptionRaised = 0
|
||
|
for xsdChildNode in xsdNode.getChildren():
|
||
|
try:
|
||
|
newIndex = self._checkParticle (xsdChildNode, inputParentNode, inputNodeList, currIndex)
|
||
|
if newIndex > currIndex:
|
||
|
currIndex = newIndex
|
||
|
childFound = 1
|
||
|
break
|
||
|
else:
|
||
|
exceptionRaised = 0
|
||
|
except TagException, errInst:
|
||
|
exceptionRaised = 1
|
||
|
else:
|
||
|
if not childFound and exceptionRaised:
|
||
|
if currIndex < len(inputNodeList):
|
||
|
currNode = inputNodeList[currIndex]
|
||
|
endTag = 0
|
||
|
else:
|
||
|
currNode = inputParentNode
|
||
|
endTag = 1
|
||
|
raise TagException ("No suitable child tag for choice found!", currNode, endTag)
|
||
|
|
||
|
return currIndex
|
||
|
|
||
|
|
||
|
########################################
|
||
|
# validate inputNode against group node
|
||
|
#
|
||
|
def _checkGroupTag (self, xsdNode, inputParentNode, inputNodeList, currIndex):
|
||
|
if xsdNode.hasAttribute("ref"):
|
||
|
refNsName = xsdNode.getQNameAttribute("ref")
|
||
|
currIndex = self._checkGroupTag (self.xsdGroupDict[refNsName], inputParentNode, inputNodeList, currIndex)
|
||
|
else:
|
||
|
for xsdChildNode in xsdNode.getChildren():
|
||
|
currIndex = self._checkParticle (xsdChildNode, inputParentNode, inputNodeList, currIndex)
|
||
|
return currIndex
|
||
|
|
||
|
|
||
|
########################################
|
||
|
# validate inputNode against all node
|
||
|
#
|
||
|
def _checkAllTag (self, xsdNode, inputParentNode, inputNodeList, currIndex):
|
||
|
oldIndex = currIndex
|
||
|
xsdChildDict = {}
|
||
|
for xsdChildNode in xsdNode.getChildren():
|
||
|
if xsdChildNode.getNsName() != (XSD_NAMESPACE, "annotation"):
|
||
|
xsdChildDict[xsdChildNode] = 0
|
||
|
while (currIndex < len(inputNodeList)) and (0 in xsdChildDict.values()):
|
||
|
currNode = inputNodeList[currIndex]
|
||
|
for xsdChildNode in xsdChildDict.keys():
|
||
|
try:
|
||
|
newIndex = self._checkParticle (xsdChildNode, inputParentNode, inputNodeList, currIndex)
|
||
|
if newIndex == currIndex:
|
||
|
continue
|
||
|
except TagException, errInst:
|
||
|
continue
|
||
|
|
||
|
if xsdChildDict[xsdChildNode] == 0:
|
||
|
xsdChildDict[xsdChildNode] = 1
|
||
|
currIndex = newIndex
|
||
|
break
|
||
|
else:
|
||
|
raise TagException ("Ambiguous child tag %s found in all-group!" %repr(currNode.getTagName()), currNode)
|
||
|
else:
|
||
|
raise TagException ("Unexpected child tag %s for all-group found!" %repr(currNode.getTagName()), currNode)
|
||
|
|
||
|
for xsdChildNode, occurs in xsdChildDict.items():
|
||
|
if xsdChildNode.getAttributeOrDefault("minOccurs", "1") != "0" and occurs == 0:
|
||
|
raise TagException ("Child tag %s missing in all-group (%s)" %(repr(xsdChildNode.getAttribute("name")), repr(inputParentNode.getTagName())), inputParentNode)
|
||
|
|
||
|
return currIndex
|
||
|
|
||
|
|
||
|
########################################
|
||
|
# validate inputNode against any node
|
||
|
#
|
||
|
def _checkAnyTag (self, xsdNode, inputParentNode, inputNodeList, currIndex):
|
||
|
if currIndex >= len (inputNodeList):
|
||
|
raise TagException ("Missing child tag (anyTag) in tag %s!" %repr(inputParentNode.getTagName()), inputParentNode, 1)
|
||
|
|
||
|
inputNode = inputNodeList[currIndex]
|
||
|
inputNamespace = inputNode.getNamespaceURI()
|
||
|
self._checkWildcardElement (xsdNode, inputNode, inputNamespace)
|
||
|
|
||
|
currIndex = currIndex + 1
|
||
|
return currIndex
|
||
|
|
||
|
|
||
|
########################################
|
||
|
# validate inputNode against particle
|
||
|
#
|
||
|
def _checkParticle (self, xsdNode, inputParentNode, inputNodeList, currIndex):
|
||
|
xsdTagName = xsdNode.getLocalName()
|
||
|
if xsdTagName == "element":
|
||
|
currIndex = self._checkList (self._checkElementTag, xsdNode, inputParentNode, inputNodeList, currIndex)
|
||
|
elif xsdTagName == "choice":
|
||
|
currIndex = self._checkList (self._checkChoiceTag, xsdNode, inputParentNode, inputNodeList, currIndex)
|
||
|
elif xsdTagName == "sequence":
|
||
|
currIndex = self._checkList (self._checkSequenceTag, xsdNode, inputParentNode, inputNodeList, currIndex)
|
||
|
elif xsdTagName == "group":
|
||
|
currIndex = self._checkList (self._checkGroupTag, xsdNode, inputParentNode, inputNodeList, currIndex)
|
||
|
elif xsdTagName == "all":
|
||
|
currIndex = self._checkList (self._checkAllTag, xsdNode, inputParentNode, inputNodeList, currIndex)
|
||
|
elif xsdTagName == "any":
|
||
|
currIndex = self._checkList (self._checkAnyTag, xsdNode, inputParentNode, inputNodeList, currIndex)
|
||
|
elif xsdTagName == "annotation":
|
||
|
# TODO: really nothing to check??
|
||
|
pass
|
||
|
else:
|
||
|
self._addError ("Internal error: Invalid tag %s found!" %repr(xsdTagName))
|
||
|
return currIndex
|
||
|
|
||
|
|
||
|
########################################
|
||
|
# validate attributes of inputNode against complexType node
|
||
|
#
|
||
|
def _checkAttributeTags (self, parentNode, xsdNode, inputNode, validAttrDict):
|
||
|
# retrieve all valid attributes for this element from the schema file
|
||
|
self._updateAttributeDict (xsdNode, validAttrDict)
|
||
|
inputAttrDict = {}
|
||
|
for iAttrName, iAttrValue in inputNode.getAttributeDict().items():
|
||
|
# skip namespace declarations
|
||
|
if iAttrName[0] != XMLNS_NAMESPACE and iAttrName[1] != "xmlns":
|
||
|
inputAttrDict[iAttrName] = iAttrValue
|
||
|
|
||
|
for qAttrName, validAttrEntry in validAttrDict.items():
|
||
|
attrRefNode = validAttrEntry["RefNode"]
|
||
|
# global attributes use always form "qualified"
|
||
|
if self.xsdAttributeDict.has_key(qAttrName) and self.xsdAttributeDict[qAttrName] == attrRefNode:
|
||
|
attributeForm = "qualified"
|
||
|
else:
|
||
|
attributeForm = attrRefNode.getAttributeOrDefault ("form", self._getAttributeFormDefault(xsdNode))
|
||
|
attrRefNode.setAttribute ("form", attributeForm)
|
||
|
self._checkAttributeTag (qAttrName, validAttrEntry["Node"], attrRefNode, inputNode, inputAttrDict)
|
||
|
|
||
|
for inputAttribute in inputAttrDict.keys():
|
||
|
if inputAttribute == (XSI_NAMESPACE, "type"):
|
||
|
pass # for attribute xsi:type refer _checkElementTag
|
||
|
elif inputAttribute == (XSI_NAMESPACE, "nil"):
|
||
|
if parentNode.getAttributeOrDefault ("nillable", "false") == "false":
|
||
|
self._addError ("Tag %s hasn't been defined as nillable!" %repr(inputNode.getTagName()), inputNode)
|
||
|
elif inputNode == self.inputRoot and inputAttribute in ((XSI_NAMESPACE, "noNamespaceSchemaLocation"), (XSI_NAMESPACE, "schemaLocation")):
|
||
|
pass
|
||
|
elif validAttrDict.has_key("__ANY_ATTRIBUTE__"):
|
||
|
xsdNode = validAttrDict["__ANY_ATTRIBUTE__"]["Node"]
|
||
|
try:
|
||
|
inputNamespace = inputAttribute[0]
|
||
|
if inputAttribute[0] == None and xsdNode.getAttribute("form") == "unqualified":
|
||
|
# TODO: Check: If only local namespace is allowed, do not use target namespace???
|
||
|
if xsdNode.getAttribute("namespace") != "##local":
|
||
|
inputNamespace = self._getTargetNamespace(xsdNode)
|
||
|
self._checkWildcardAttribute (xsdNode, inputNode, inputAttribute, inputNamespace, inputAttrDict)
|
||
|
except TagException:
|
||
|
self._addError ("Unexpected attribute %s in Tag %s!" %(repr(inputAttribute), repr(inputNode.getTagName())), inputNode)
|
||
|
else:
|
||
|
self._addError ("Unexpected attribute %s in Tag %s!" %(repr(inputAttribute), repr(inputNode.getTagName())), inputNode)
|
||
|
|
||
|
|
||
|
########################################
|
||
|
# validate one attribute (defined by xsdNode) of inputNode
|
||
|
#
|
||
|
def _checkAttributeTag (self, qAttrName, xsdAttrNode, xsdAttrRefNode, inputNode, inputAttrDict):
|
||
|
targetNamespace = self._getTargetNamespace(xsdAttrNode)
|
||
|
if qAttrName[0] == targetNamespace and xsdAttrRefNode.getAttribute("form") == "unqualified":
|
||
|
qAttrName = NsNameTupleFactory( (None, qAttrName[1]) )
|
||
|
|
||
|
use = xsdAttrNode.getAttribute("use")
|
||
|
if use == None: use = xsdAttrRefNode.getAttributeOrDefault ("use", "optional")
|
||
|
fixedValue = xsdAttrNode.getAttribute("fixed")
|
||
|
if fixedValue == None:
|
||
|
fixedValue = xsdAttrRefNode.getAttribute("fixed")
|
||
|
|
||
|
if inputAttrDict.has_key(qAttrName):
|
||
|
if use == "prohibited":
|
||
|
self._addError ("Attribute %s is prohibited in this context!" %repr(qAttrName[1]), inputNode)
|
||
|
elif inputAttrDict.has_key((targetNamespace, qAttrName[1])):
|
||
|
self._addError ("Local attribute %s must be unqualified!" %(repr(qAttrName)), inputNode)
|
||
|
del inputAttrDict[(targetNamespace, qAttrName[1])]
|
||
|
elif inputAttrDict.has_key((None, qAttrName[1])) and qAttrName[0] == targetNamespace:
|
||
|
self._addError ("Attribute %s must be qualified!" %repr(qAttrName[1]), inputNode)
|
||
|
del inputAttrDict[(None, qAttrName[1])]
|
||
|
else:
|
||
|
if use == "required":
|
||
|
self._addError ("Attribute %s is missing!" %(repr(qAttrName)), inputNode)
|
||
|
elif use == "optional":
|
||
|
if xsdAttrRefNode.hasAttribute("default"):
|
||
|
if not (inputNode.getNsName() == (XSD_NAMESPACE, "element") and
|
||
|
inputNode.hasAttribute("ref") and
|
||
|
xsdAttrRefNode.getAttribute("name") == "nillable"):
|
||
|
defaultValue = xsdAttrRefNode.getAttribute("default")
|
||
|
inputNode.setAttribute(qAttrName, defaultValue)
|
||
|
inputAttrDict[qAttrName] = defaultValue
|
||
|
elif fixedValue != None:
|
||
|
inputNode.setAttribute(qAttrName, fixedValue)
|
||
|
inputAttrDict[qAttrName] = fixedValue
|
||
|
|
||
|
if inputAttrDict.has_key(qAttrName):
|
||
|
attributeValue = inputAttrDict[qAttrName]
|
||
|
self._checkSimpleType (xsdAttrRefNode, "type", inputNode, qAttrName, attributeValue, fixedValue, 1)
|
||
|
del inputAttrDict[qAttrName]
|
||
|
inputNode.setXsdAttrNode(qAttrName, xsdAttrRefNode)
|
||
|
|
||
|
|
||
|
########################################
|
||
|
# update dictionary of valid attributes
|
||
|
#
|
||
|
def _updateAttributeDict (self, xsdNode, validAttrDict, checkForDuplicateAttr=0, recursionKeys=None):
|
||
|
# TODO: Why can recursionKeys not be initialized by default variable??
|
||
|
if recursionKeys == None: recursionKeys = {}
|
||
|
validAttributeNodes = xsdNode.getChildrenNS(self.xsdNsURI, "attribute")
|
||
|
for validAttrGroup in xsdNode.getChildrenNS(self.xsdNsURI, "attributeGroup"):
|
||
|
refNsName = validAttrGroup.getQNameAttribute("ref")
|
||
|
if self.xsdAttrGroupDict.has_key(refNsName):
|
||
|
if recursionKeys.has_key(refNsName):
|
||
|
self._addError ("Circular definition for attribute group %s detected!" %(repr(refNsName)), validAttrGroup)
|
||
|
continue
|
||
|
recursionKeys[refNsName] = 1
|
||
|
self._updateAttributeDict(self.xsdAttrGroupDict[refNsName], validAttrDict, checkForDuplicateAttr, recursionKeys)
|
||
|
|
||
|
|
||
|
for validAttributeNode in validAttributeNodes:
|
||
|
if validAttributeNode.hasAttribute("ref"):
|
||
|
attrKey = validAttributeNode.getQNameAttribute("ref")
|
||
|
attributeRefNode = self.xsdAttributeDict[attrKey]
|
||
|
else:
|
||
|
attrKey = validAttributeNode.getQNameAttribute("name")
|
||
|
attrKey = (self._getTargetNamespace(validAttributeNode), validAttributeNode.getAttribute("name"))
|
||
|
attributeRefNode = validAttributeNode
|
||
|
|
||
|
if checkForDuplicateAttr and validAttrDict.has_key(attrKey):
|
||
|
self._addError ("Duplicate attribute %s found!" %repr(attrKey), validAttributeNode)
|
||
|
else:
|
||
|
validAttrDict[attrKey] = {"Node":validAttributeNode, "RefNode":attributeRefNode}
|
||
|
|
||
|
anyAttributeNode = xsdNode.getFirstChildNS(self.xsdNsURI, "anyAttribute")
|
||
|
if anyAttributeNode != None:
|
||
|
validAttrDict["__ANY_ATTRIBUTE__"] = {"Node":anyAttributeNode, "RefNode":anyAttributeNode}
|
||
|
|
||
|
|
||
|
########################################
|
||
|
# validate wildcard specification of anyElement
|
||
|
#
|
||
|
def _checkWildcardElement (self, xsdNode, inputNode, inputNamespace):
|
||
|
processContents = xsdNode.getAttributeOrDefault("processContents", "lax")
|
||
|
|
||
|
self._checkInputNamespace (xsdNode, inputNode, inputNamespace)
|
||
|
|
||
|
inputNsName = inputNode.getNsName()
|
||
|
if processContents == "skip":
|
||
|
pass
|
||
|
else:
|
||
|
if inputNode.hasAttribute((XSI_NAMESPACE, "type")):
|
||
|
# overloaded type is used
|
||
|
typeNsName = inputNode.getQNameAttribute((XSI_NAMESPACE, "type"))
|
||
|
if not self.xsdTypeDict.has_key(typeNsName):
|
||
|
self._addError ("Unknown overloaded type %s!" %(repr(typeNsName)), inputNode, 0)
|
||
|
else:
|
||
|
typeType = self.xsdTypeDict[typeNsName].getLocalName()
|
||
|
if typeType == "complexType":
|
||
|
try:
|
||
|
self._checkComplexTypeTag (None, self.xsdTypeDict[typeNsName], inputNode, 0)
|
||
|
except TagException, errInst:
|
||
|
self._addError (errInst.errstr, errInst.node, errInst.endTag)
|
||
|
else:
|
||
|
simpleTypeReturnDict = {"BaseTypes":[], "primitiveType":None}
|
||
|
try:
|
||
|
self.simpleTypeVal.checkSimpleType (inputNode, inputNode.getLocalName(), typeNsName, inputNode.getElementValue(), simpleTypeReturnDict, idCheck=1)
|
||
|
except SimpleTypeError, errInst:
|
||
|
self._addError (errInst.args[0], inputNode)
|
||
|
|
||
|
elif self.xsdElementDict.has_key(inputNsName):
|
||
|
self._checkElementTag (self.xsdElementDict[inputNsName], None, (inputNode,), 0)
|
||
|
|
||
|
elif processContents == "strict":
|
||
|
self._addError ("Element definition %s not found in schema file!" %repr(inputNsName), inputNode)
|
||
|
|
||
|
|
||
|
########################################
|
||
|
# validate wildcard specification of anyElement/anyAttribute
|
||
|
#
|
||
|
def _checkWildcardAttribute (self, xsdNode, inputNode, qAttrName, inputNamespace, inputAttrDict):
|
||
|
processContents = xsdNode.getAttributeOrDefault("processContents", "strict")
|
||
|
|
||
|
self._checkInputNamespace (xsdNode, inputNode, inputNamespace)
|
||
|
|
||
|
if processContents == "skip":
|
||
|
pass
|
||
|
elif processContents == "lax":
|
||
|
if self.xsdAttributeDict.has_key(qAttrName):
|
||
|
attrNode = self.xsdAttributeDict[qAttrName]
|
||
|
self._checkAttributeTag (qAttrName, attrNode, attrNode, inputNode, inputAttrDict)
|
||
|
elif processContents == "strict":
|
||
|
if self.xsdAttributeDict.has_key(qAttrName):
|
||
|
attrNode = self.xsdAttributeDict[qAttrName]
|
||
|
self._checkAttributeTag (qAttrName, attrNode, attrNode, inputNode, inputAttrDict)
|
||
|
else:
|
||
|
self._addError ("Attribute definition %s not found in schema file!" %repr(qAttrName), inputNode)
|
||
|
|
||
|
|
||
|
########################################
|
||
|
# validate wildcard specification of anyElement/anyAttribute
|
||
|
#
|
||
|
def _checkInputNamespace (self, xsdNode, inputNode, inputNamespace):
|
||
|
targetNamespace = self._getTargetNamespace(xsdNode)
|
||
|
namespaces = xsdNode.getAttributeOrDefault("namespace", "##any")
|
||
|
if namespaces == "##any":
|
||
|
pass # nothing to check
|
||
|
elif namespaces == "##other":
|
||
|
if inputNamespace == targetNamespace or inputNamespace == None:
|
||
|
raise TagException ("Node or attribute must not be part of target namespace or local!", inputNode)
|
||
|
else:
|
||
|
for namespace in string.split(collapseString(namespaces), " "):
|
||
|
if namespace == "##local" and inputNamespace == None:
|
||
|
break
|
||
|
elif namespace == "##targetNamespace" and inputNamespace == targetNamespace:
|
||
|
break
|
||
|
elif namespace == inputNamespace:
|
||
|
break
|
||
|
else:
|
||
|
raise TagException ("Node or attribute is not part of namespace %s!" %repr(namespaces), inputNode)
|
||
|
|
||
|
|
||
|
########################################
|
||
|
# validate unique and key definition
|
||
|
#
|
||
|
def _checkIdentityConstraint (self, identityConstrNode, inputNode):
|
||
|
identConstrTag = identityConstrNode.getLocalName()
|
||
|
identConstrName = identityConstrNode.getAttribute ("name")
|
||
|
identConstrNsLocalName = (self._getTargetNamespace(identityConstrNode), identConstrName)
|
||
|
selectorXPathNode = identityConstrNode.getFirstChildNS (self.xsdNsURI, "selector")
|
||
|
selectorNodeList, dummy, dummy = self._getXPath (inputNode, selectorXPathNode)
|
||
|
|
||
|
valueDict = {}
|
||
|
for selectorNode in selectorNodeList:
|
||
|
fieldXPathNodeList = identityConstrNode.getChildrenNS (self.xsdNsURI, "field")
|
||
|
keyValue = []
|
||
|
baseTypesList = []
|
||
|
for fieldXPathNode in fieldXPathNodeList:
|
||
|
fieldChildList, attrNodeList, attrName = self._getXPath (selectorNode, fieldXPathNode, identConstrTag)
|
||
|
if len(fieldChildList) > 1:
|
||
|
self._addError ("The field xPath %s of %s %s must evaluate to exactly 0 or 1 node!" %(repr(fieldXPathNode["xpath"]), repr(identConstrTag), repr(identConstrName)), selectorNode)
|
||
|
return
|
||
|
|
||
|
for fieldChild in fieldChildList:
|
||
|
if attrNodeList == []:
|
||
|
inputChild = fieldChild
|
||
|
try:
|
||
|
baseTypes = self._setBaseTypes(fieldChild.getXsdNode())
|
||
|
except:
|
||
|
baseTypes = ((XSD_NAMESPACE, "anyType"),)
|
||
|
value = fieldChild.getElementValue()
|
||
|
else:
|
||
|
inputChild = attrNodeList[0]
|
||
|
try:
|
||
|
baseTypes = self._setBaseTypes(attrNodeList[0].getXsdAttrNode(attrName))
|
||
|
except:
|
||
|
baseTypes = ((XSD_NAMESPACE, "anyType"),)
|
||
|
value = fieldChild
|
||
|
if baseTypes != None:
|
||
|
if baseTypes[0] in ((XSD_NAMESPACE, "anyType"), (XSD_NAMESPACE, "anySimpleType")):
|
||
|
overloadedType = inputChild.getQNameAttribute((XSI_NAMESPACE, "type"))
|
||
|
if overloadedType != (None, None):
|
||
|
baseTypes = [inputChild.getQNameAttribute((XSI_NAMESPACE, "type")),]
|
||
|
else:
|
||
|
self._addError ("Identity constraint does not have a simple type!", inputChild)
|
||
|
continue
|
||
|
|
||
|
baseTypesList.append(baseTypes)
|
||
|
for baseType in baseTypes:
|
||
|
try:
|
||
|
value = self._getOrderedValue (inputChild, attrName, baseType, value)
|
||
|
break
|
||
|
except SimpleTypeError, errInst:
|
||
|
pass
|
||
|
keyValue.append (value)
|
||
|
|
||
|
if keyValue != []:
|
||
|
keyValue = tuple(keyValue)
|
||
|
if not valueDict.has_key (keyValue):
|
||
|
valueDict[keyValue] = 1
|
||
|
self.xsdIdentityConstrDict[identConstrNsLocalName]["ValueDict"][keyValue] = baseTypesList
|
||
|
else:
|
||
|
if len(keyValue) == 1:
|
||
|
self._addError ("Duplicate identity constraint values %s found for identity contraint %s!" %(repr(keyValue[0]), repr(identConstrName)), selectorNode)
|
||
|
else:
|
||
|
self._addError ("Duplicate identity constraint values %s found for identity contraint %s!" %(repr(keyValue), repr(identConstrName)), selectorNode)
|
||
|
|
||
|
########################################
|
||
|
# validate unique and key definition
|
||
|
#
|
||
|
def _checkKeyRefConstraint (self, keyrefNode, inputNode):
|
||
|
keyRefName = keyrefNode.getAttribute ("name")
|
||
|
keyReference = keyrefNode.getQNameAttribute ("refer")
|
||
|
|
||
|
selectorXPathNode = keyrefNode.getFirstChildNS (self.xsdNsURI, "selector")
|
||
|
selectorNodeList, dummy, dummy = self._getXPath (inputNode, selectorXPathNode)
|
||
|
for selectorNode in selectorNodeList:
|
||
|
fieldXPathNodeList = keyrefNode.getChildrenNS(self.xsdNsURI, "field")
|
||
|
keyValue = []
|
||
|
for fieldXPathNode in fieldXPathNodeList:
|
||
|
fieldChildList, attrNodeList, attrName = self._getXPath (selectorNode, fieldXPathNode, "keyref")
|
||
|
if len(fieldChildList) > 1:
|
||
|
self._addError ("The field xPath of keyref %s must evaluate to exactly 0 or 1 node!" %repr(keyRefName), fieldXPathNode)
|
||
|
return
|
||
|
|
||
|
for fieldChild in fieldChildList:
|
||
|
if attrNodeList == []:
|
||
|
inputChild = fieldChild
|
||
|
baseTypes = self._setBaseTypes(fieldChild.getXsdNode())
|
||
|
value = fieldChild.getElementValue()
|
||
|
else:
|
||
|
inputChild = attrNodeList[0]
|
||
|
baseTypes = self._setBaseTypes(attrNodeList[0].getXsdAttrNode(attrName))
|
||
|
value = fieldChild
|
||
|
|
||
|
if baseTypes != None:
|
||
|
for baseType in baseTypes:
|
||
|
try:
|
||
|
value = self._getOrderedValue (inputChild, attrName, baseType, value)
|
||
|
break
|
||
|
except SimpleTypeError, errInst:
|
||
|
pass
|
||
|
keyValue.append (value)
|
||
|
|
||
|
keyValue = tuple(keyValue)
|
||
|
if keyValue != ():
|
||
|
if not self.xsdIdentityConstrDict[keyReference]["ValueDict"].has_key (keyValue):
|
||
|
self._addError ("Key reference value %s is undefined for key type %s!" %(repr(keyValue), repr(keyReference)), selectorNode)
|
||
|
else:
|
||
|
baseTypesList = self.xsdIdentityConstrDict[keyReference]["ValueDict"][keyValue]
|
||
|
for fieldXPathNode, baseTypes in zip(fieldXPathNodeList, baseTypesList):
|
||
|
fieldChildList, attrNodeList, attrName = self._getXPath (selectorNode, fieldXPathNode, "keyref")
|
||
|
if attrNodeList == []:
|
||
|
inputChild = fieldChildList[0]
|
||
|
refBaseTypes = self._setBaseTypes(fieldChildList[0].getXsdNode())
|
||
|
else:
|
||
|
inputChild = attrNodeList[0]
|
||
|
refBaseTypes = self._setBaseTypes(inputChild.getXsdAttrNode(attrName))
|
||
|
if baseTypes[0] not in refBaseTypes and refBaseTypes[0] not in baseTypes:
|
||
|
if baseTypes[0] != (XSD_NAMESPACE, "anyType") and refBaseTypes[0] != (XSD_NAMESPACE, "anyType"):
|
||
|
self._addError ("Key type and key reference type does not match (%s != %s)!" %(repr(baseTypes[0]), repr(refBaseTypes[0])), inputChild)
|
||
|
|
||
|
|
||
|
########################################
|
||
|
# check input element form
|
||
|
#
|
||
|
def _checkInputElementForm (self, xsdNode, xsdNodeNameAttr, inputNode):
|
||
|
targetNamespace = self._getTargetNamespace(xsdNode)
|
||
|
nsNameAttr = (targetNamespace, xsdNodeNameAttr)
|
||
|
if self.xsdElementDict.has_key(nsNameAttr) and self.xsdElementDict[nsNameAttr] == xsdNode:
|
||
|
elementForm = "qualified"
|
||
|
else:
|
||
|
elementForm = xsdNode.getAttributeOrDefault ("form", self._getElementFormDefault(xsdNode))
|
||
|
if elementForm == "qualified":
|
||
|
if inputNode.getNamespaceURI() == None:
|
||
|
if targetNamespace != None:
|
||
|
self._addError ("Element %s must be qualified!" %repr(xsdNodeNameAttr), inputNode)
|
||
|
elif inputNode.getNamespaceURI() != targetNamespace:
|
||
|
self._addError ("%s undefined in specified namespace!" %repr(xsdNodeNameAttr), inputNode)
|
||
|
elif elementForm == "unqualified" and inputNode.getNamespaceURI() != None:
|
||
|
self._addError ("Local element %s must be unqualified!" %repr(xsdNodeNameAttr), inputNode)
|
||
|
|
||
|
|
||
|
########################################
|
||
|
# retrieve ordered value and base types of given typeNsName
|
||
|
#
|
||
|
def _getOrderedValue (self, inputNode, attrName, typeNsName, attrValue):
|
||
|
simpleTypeReturnDict = {"BaseTypes":[], "primitiveType":None}
|
||
|
self.simpleTypeVal.checkSimpleType (inputNode, attrName, typeNsName, attrValue, simpleTypeReturnDict, idCheck=1)
|
||
|
if simpleTypeReturnDict.has_key("orderedValue"):
|
||
|
attrValue = simpleTypeReturnDict["orderedValue"]
|
||
|
return attrValue
|
||
|
|
||
|
|
||
|
########################################
|
||
|
# retrieve nodes/attributes specified by given xPath
|
||
|
#
|
||
|
def _getXPath (self, node, xPathNode, identityConstraint=None):
|
||
|
xPath = xPathNode.getAttribute("xpath")
|
||
|
try:
|
||
|
attrIgnoreList = [(XSI_NAMESPACE, "nil")]
|
||
|
childList, attrNodeList, attrName = node.getXPathList (xPath, namespaceRef=xPathNode, useDefaultNs=0, attrIgnoreList=attrIgnoreList)
|
||
|
except Exception, errInst:
|
||
|
self._addError (errInst.args, node)
|
||
|
childList = []
|
||
|
attrNodeList = []
|
||
|
attrName = None
|
||
|
|
||
|
if childList == []:
|
||
|
if identityConstraint == "key":
|
||
|
self.errorHandler.addError ("Key is missing! XPath = %s!" %repr(xPath), node)
|
||
|
elif identityConstraint in ("unique", "keyref"):
|
||
|
self.errorHandler.addWarning ("Identity constraint is missing! XPath = %s!" %repr(xPath), node)
|
||
|
return childList, attrNodeList, attrName
|
||
|
|
||
|
|
||
|
########################################
|
||
|
# retrieve basetypes from XML attribute (string format)
|
||
|
#
|
||
|
def _setBaseTypes (self, xsdNode):
|
||
|
if xsdNode.getAttribute("BaseTypes") != None:
|
||
|
baseTypes = string.split(xsdNode["BaseTypes"])
|
||
|
baseTypeList = map (lambda basetype: NsNameTupleFactory(basetype), baseTypes)
|
||
|
if baseTypeList != []:
|
||
|
return baseTypeList
|
||
|
else:
|
||
|
return None
|
||
|
else:
|
||
|
return None
|
||
|
|
||
|
########################################
|
||
|
# retrieve target namespace attribute for given node
|
||
|
#
|
||
|
def _getTargetNamespace(self, node):
|
||
|
schemaRootNode = node.getSchemaRootNode()
|
||
|
return schemaRootNode.getAttribute("targetNamespace")
|
||
|
|
||
|
|
||
|
########################################
|
||
|
# retrieve element form default attribute for given node
|
||
|
#
|
||
|
def _getElementFormDefault(self, node):
|
||
|
schemaRootNode = node.getSchemaRootNode()
|
||
|
return schemaRootNode.getAttributeOrDefault("elementFormDefault", "unqualified")
|
||
|
|
||
|
########################################
|
||
|
# retrieve element form default attribute for given node
|
||
|
#
|
||
|
def _getAttributeFormDefault(self, node):
|
||
|
schemaRootNode = node.getSchemaRootNode()
|
||
|
return schemaRootNode.getAttributeOrDefault("attributeFormDefault", "unqualified")
|
||
|
|
||
|
|
||
|
########################################
|
||
|
# define own exception for XML schema validation errors
|
||
|
#
|
||
|
class TagException (StandardError):
|
||
|
def __init__ (self, errstr="", node=None, endTag=0):
|
||
|
self.node = node
|
||
|
self.errstr = errstr
|
||
|
self.endTag = endTag
|
||
|
StandardError.__init__(self)
|
||
|
|