|
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 |