1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 """
18 The I{doctor} module provides classes for fixing broken (sick)
19 schema(s).
20 """
21
22 from logging import getLogger
23 from suds.sax import splitPrefix, Namespace
24 from suds.sax.element import Element
25 from suds.plugin import DocumentPlugin, DocumentContext
26
27 log = getLogger(__name__)
28
29
31 """
32 Schema Doctor.
33 """
35 """
36 Examine and repair the schema (if necessary).
37 @param root: A schema root element.
38 @type root: L{Element}
39 """
40 pass
41
42
44 """
45 A collection of doctors.
46 @ivar doctors: A list of doctors.
47 @type doctors: list
48 """
49
52
53 - def add(self, doctor):
54 """
55 Add a doctor to the practice
56 @param doctor: A doctor to add.
57 @type doctor: L{Doctor}
58 """
59 self.doctors.append(doctor)
60
65
66
68 """
69 Target Namespace filter.
70 @ivar tns: A list of target namespaces.
71 @type tns: [str,...]
72 """
73
75 """
76 @param tns: A list of target namespaces.
77 @type tns: [str,...]
78 """
79 self.tns = []
80 self.add(*tns)
81
82 - def add(self, *tns):
83 """
84 Add I{targetNamesapces} to be added.
85 @param tns: A list of target namespaces.
86 @type tns: [str,...]
87 """
88 self.tns += tns
89
90 - def match(self, root, ns):
91 """
92 Match by I{targetNamespace} excluding those that
93 are equal to the specified namespace to prevent
94 adding an import to itself.
95 @param root: A schema root.
96 @type root: L{Element}
97 """
98 tns = root.get('targetNamespace')
99 if len(self.tns):
100 matched = ( tns in self.tns )
101 else:
102 matched = 1
103 itself = ( ns == tns )
104 return ( matched and not itself )
105
106
108 """
109 An <xs:import/> to be applied.
110 @cvar xsdns: The XSD namespace.
111 @type xsdns: (p,u)
112 @ivar ns: An import namespace.
113 @type ns: str
114 @ivar location: An optional I{schemaLocation}.
115 @type location: str
116 @ivar filter: A filter used to restrict application to
117 a particular schema.
118 @type filter: L{TnsFilter}
119 """
120
121 xsdns = Namespace.xsdns
122
124 """
125 @param ns: An import namespace.
126 @type ns: str
127 @param location: An optional I{schemaLocation}.
128 @type location: str
129 """
130 self.ns = ns
131 self.location = location
132 self.filter = TnsFilter()
133
135 """
136 Set the filter.
137 @param filter: A filter to set.
138 @type filter: L{TnsFilter}
139 """
140 self.filter = filter
141
143 """
144 Apply the import (rule) to the specified schema.
145 If the schema does not already contain an import for the
146 I{namespace} specified here, it is added.
147 @param root: A schema root.
148 @type root: L{Element}
149 """
150 if not self.filter.match(root, self.ns):
151 return
152 if self.exists(root):
153 return
154 node = Element('import', ns=self.xsdns)
155 node.set('namespace', self.ns)
156 if self.location is not None:
157 node.set('schemaLocation', self.location)
158 log.debug('inserting: %s', node)
159 root.insert(node)
160
161 - def add(self, root):
162 """
163 Add an <xs:import/> to the specified schema root.
164 @param root: A schema root.
165 @type root: L{Element}
166 """
167 node = Element('import', ns=self.xsdns)
168 node.set('namespace', self.ns)
169 if self.location is not None:
170 node.set('schemaLocation', self.location)
171 log.debug('%s inserted', node)
172 root.insert(node)
173
175 """
176 Check to see if the <xs:import/> already exists
177 in the specified schema root by matching I{namesapce}.
178 @param root: A schema root.
179 @type root: L{Element}
180 """
181 for node in root.children:
182 if node.name != 'import':
183 continue
184 ns = node.get('namespace')
185 if self.ns == ns:
186 return 1
187 return 0
188
189
191 """
192 Doctor used to fix missing imports.
193 @ivar imports: A list of imports to apply.
194 @type imports: [L{Import},...]
195 """
196
198 """
199 """
200 self.imports = []
201 self.add(*imports)
202
203 - def add(self, *imports):
204 """
205 Add a namesapce to be checked.
206 @param imports: A list of L{Import} objects.
207 @type imports: [L{Import},..]
208 """
209 self.imports += imports
210
212 for imp in self.imports:
213 imp.apply(node)
214
226