lxml 6.0.0__cp310-cp310-win_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lxml/ElementInclude.py +244 -0
- lxml/__init__.py +22 -0
- lxml/_elementpath.cp310-win_arm64.pyd +0 -0
- lxml/_elementpath.py +343 -0
- lxml/apihelpers.pxi +1801 -0
- lxml/builder.cp310-win_arm64.pyd +0 -0
- lxml/builder.py +243 -0
- lxml/classlookup.pxi +580 -0
- lxml/cleanup.pxi +215 -0
- lxml/cssselect.py +101 -0
- lxml/debug.pxi +36 -0
- lxml/docloader.pxi +178 -0
- lxml/doctestcompare.py +488 -0
- lxml/dtd.pxi +479 -0
- lxml/etree.cp310-win_arm64.pyd +0 -0
- lxml/etree.h +244 -0
- lxml/etree.pyx +3853 -0
- lxml/etree_api.h +204 -0
- lxml/extensions.pxi +830 -0
- lxml/html/ElementSoup.py +10 -0
- lxml/html/__init__.py +1927 -0
- lxml/html/_diffcommand.py +86 -0
- lxml/html/_difflib.cp310-win_arm64.pyd +0 -0
- lxml/html/_difflib.py +2106 -0
- lxml/html/_html5builder.py +100 -0
- lxml/html/_setmixin.py +56 -0
- lxml/html/builder.py +173 -0
- lxml/html/clean.py +21 -0
- lxml/html/defs.py +135 -0
- lxml/html/diff.cp310-win_arm64.pyd +0 -0
- lxml/html/diff.py +972 -0
- lxml/html/formfill.py +299 -0
- lxml/html/html5parser.py +260 -0
- lxml/html/soupparser.py +314 -0
- lxml/html/usedoctest.py +13 -0
- lxml/includes/__init__.pxd +0 -0
- lxml/includes/__init__.py +0 -0
- lxml/includes/c14n.pxd +25 -0
- lxml/includes/config.pxd +3 -0
- lxml/includes/dtdvalid.pxd +18 -0
- lxml/includes/etree_defs.h +379 -0
- lxml/includes/etreepublic.pxd +237 -0
- lxml/includes/extlibs/__init__.py +0 -0
- lxml/includes/extlibs/zconf.h +543 -0
- lxml/includes/extlibs/zlib.h +1938 -0
- lxml/includes/htmlparser.pxd +56 -0
- lxml/includes/libexslt/__init__.py +0 -0
- lxml/includes/libexslt/exslt.h +108 -0
- lxml/includes/libexslt/exsltconfig.h +70 -0
- lxml/includes/libexslt/exsltexports.h +63 -0
- lxml/includes/libexslt/libexslt.h +29 -0
- lxml/includes/libxml/HTMLparser.h +320 -0
- lxml/includes/libxml/HTMLtree.h +147 -0
- lxml/includes/libxml/SAX.h +204 -0
- lxml/includes/libxml/SAX2.h +173 -0
- lxml/includes/libxml/__init__.py +0 -0
- lxml/includes/libxml/c14n.h +128 -0
- lxml/includes/libxml/catalog.h +182 -0
- lxml/includes/libxml/chvalid.h +230 -0
- lxml/includes/libxml/debugXML.h +217 -0
- lxml/includes/libxml/dict.h +81 -0
- lxml/includes/libxml/encoding.h +233 -0
- lxml/includes/libxml/entities.h +151 -0
- lxml/includes/libxml/globals.h +529 -0
- lxml/includes/libxml/hash.h +236 -0
- lxml/includes/libxml/list.h +137 -0
- lxml/includes/libxml/nanoftp.h +186 -0
- lxml/includes/libxml/nanohttp.h +81 -0
- lxml/includes/libxml/parser.h +1265 -0
- lxml/includes/libxml/parserInternals.h +662 -0
- lxml/includes/libxml/pattern.h +100 -0
- lxml/includes/libxml/relaxng.h +218 -0
- lxml/includes/libxml/schemasInternals.h +958 -0
- lxml/includes/libxml/schematron.h +142 -0
- lxml/includes/libxml/threads.h +94 -0
- lxml/includes/libxml/tree.h +1314 -0
- lxml/includes/libxml/uri.h +94 -0
- lxml/includes/libxml/valid.h +448 -0
- lxml/includes/libxml/xinclude.h +129 -0
- lxml/includes/libxml/xlink.h +189 -0
- lxml/includes/libxml/xmlIO.h +369 -0
- lxml/includes/libxml/xmlautomata.h +146 -0
- lxml/includes/libxml/xmlerror.h +919 -0
- lxml/includes/libxml/xmlexports.h +50 -0
- lxml/includes/libxml/xmlmemory.h +228 -0
- lxml/includes/libxml/xmlmodule.h +57 -0
- lxml/includes/libxml/xmlreader.h +428 -0
- lxml/includes/libxml/xmlregexp.h +222 -0
- lxml/includes/libxml/xmlsave.h +88 -0
- lxml/includes/libxml/xmlschemas.h +246 -0
- lxml/includes/libxml/xmlschemastypes.h +152 -0
- lxml/includes/libxml/xmlstring.h +140 -0
- lxml/includes/libxml/xmlunicode.h +202 -0
- lxml/includes/libxml/xmlversion.h +526 -0
- lxml/includes/libxml/xmlwriter.h +488 -0
- lxml/includes/libxml/xpath.h +575 -0
- lxml/includes/libxml/xpathInternals.h +632 -0
- lxml/includes/libxml/xpointer.h +137 -0
- lxml/includes/libxslt/__init__.py +0 -0
- lxml/includes/libxslt/attributes.h +39 -0
- lxml/includes/libxslt/documents.h +93 -0
- lxml/includes/libxslt/extensions.h +262 -0
- lxml/includes/libxslt/extra.h +72 -0
- lxml/includes/libxslt/functions.h +78 -0
- lxml/includes/libxslt/imports.h +75 -0
- lxml/includes/libxslt/keys.h +53 -0
- lxml/includes/libxslt/libxslt.h +36 -0
- lxml/includes/libxslt/namespaces.h +68 -0
- lxml/includes/libxslt/numbersInternals.h +73 -0
- lxml/includes/libxslt/preproc.h +43 -0
- lxml/includes/libxslt/security.h +104 -0
- lxml/includes/libxslt/templates.h +77 -0
- lxml/includes/libxslt/transform.h +207 -0
- lxml/includes/libxslt/trio.h +216 -0
- lxml/includes/libxslt/triodef.h +220 -0
- lxml/includes/libxslt/variables.h +118 -0
- lxml/includes/libxslt/win32config.h +51 -0
- lxml/includes/libxslt/xslt.h +110 -0
- lxml/includes/libxslt/xsltInternals.h +1992 -0
- lxml/includes/libxslt/xsltconfig.h +179 -0
- lxml/includes/libxslt/xsltexports.h +64 -0
- lxml/includes/libxslt/xsltlocale.h +44 -0
- lxml/includes/libxslt/xsltutils.h +343 -0
- lxml/includes/lxml-version.h +3 -0
- lxml/includes/relaxng.pxd +64 -0
- lxml/includes/schematron.pxd +34 -0
- lxml/includes/tree.pxd +492 -0
- lxml/includes/uri.pxd +5 -0
- lxml/includes/xinclude.pxd +22 -0
- lxml/includes/xmlerror.pxd +852 -0
- lxml/includes/xmlparser.pxd +303 -0
- lxml/includes/xmlschema.pxd +35 -0
- lxml/includes/xpath.pxd +136 -0
- lxml/includes/xslt.pxd +190 -0
- lxml/isoschematron/__init__.py +348 -0
- lxml/isoschematron/resources/rng/iso-schematron.rng +709 -0
- lxml/isoschematron/resources/xsl/RNG2Schtrn.xsl +75 -0
- lxml/isoschematron/resources/xsl/XSD2Schtrn.xsl +77 -0
- lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_abstract_expand.xsl +313 -0
- lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_dsdl_include.xsl +1160 -0
- lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_schematron_message.xsl +55 -0
- lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_schematron_skeleton_for_xslt1.xsl +1796 -0
- lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_svrl_for_xslt1.xsl +588 -0
- lxml/isoschematron/resources/xsl/iso-schematron-xslt1/readme.txt +84 -0
- lxml/iterparse.pxi +438 -0
- lxml/lxml.etree.h +244 -0
- lxml/lxml.etree_api.h +204 -0
- lxml/nsclasses.pxi +281 -0
- lxml/objectify.cp310-win_arm64.pyd +0 -0
- lxml/objectify.pyx +2149 -0
- lxml/objectpath.pxi +332 -0
- lxml/parser.pxi +2059 -0
- lxml/parsertarget.pxi +180 -0
- lxml/proxy.pxi +619 -0
- lxml/public-api.pxi +178 -0
- lxml/pyclasslookup.py +3 -0
- lxml/readonlytree.pxi +565 -0
- lxml/relaxng.pxi +165 -0
- lxml/sax.cp310-win_arm64.pyd +0 -0
- lxml/sax.py +286 -0
- lxml/saxparser.pxi +875 -0
- lxml/schematron.pxi +173 -0
- lxml/serializer.pxi +1849 -0
- lxml/usedoctest.py +13 -0
- lxml/xinclude.pxi +67 -0
- lxml/xmlerror.pxi +1654 -0
- lxml/xmlid.pxi +179 -0
- lxml/xmlschema.pxi +215 -0
- lxml/xpath.pxi +487 -0
- lxml/xslt.pxi +957 -0
- lxml/xsltext.pxi +242 -0
- lxml-6.0.0.dist-info/METADATA +163 -0
- lxml-6.0.0.dist-info/RECORD +177 -0
- lxml-6.0.0.dist-info/WHEEL +5 -0
- lxml-6.0.0.dist-info/licenses/LICENSE.txt +31 -0
- lxml-6.0.0.dist-info/licenses/LICENSES.txt +29 -0
- lxml-6.0.0.dist-info/top_level.txt +1 -0
lxml/dtd.pxi
ADDED
@@ -0,0 +1,479 @@
|
|
1
|
+
# support for DTD validation
|
2
|
+
from lxml.includes cimport dtdvalid
|
3
|
+
|
4
|
+
cdef class DTDError(LxmlError):
|
5
|
+
"""Base class for DTD errors.
|
6
|
+
"""
|
7
|
+
|
8
|
+
cdef class DTDParseError(DTDError):
|
9
|
+
"""Error while parsing a DTD.
|
10
|
+
"""
|
11
|
+
|
12
|
+
cdef class DTDValidateError(DTDError):
|
13
|
+
"""Error while validating an XML document with a DTD.
|
14
|
+
"""
|
15
|
+
|
16
|
+
|
17
|
+
cdef inline int _assertValidDTDNode(node, void *c_node) except -1:
|
18
|
+
assert c_node is not NULL, "invalid DTD proxy at %s" % id(node)
|
19
|
+
|
20
|
+
|
21
|
+
@cython.final
|
22
|
+
@cython.internal
|
23
|
+
@cython.freelist(8)
|
24
|
+
cdef class _DTDElementContentDecl:
|
25
|
+
cdef DTD _dtd
|
26
|
+
cdef tree.xmlElementContent* _c_node
|
27
|
+
|
28
|
+
def __repr__(self):
|
29
|
+
return "<%s.%s object name=%r type=%r occur=%r at 0x%x>" % (self.__class__.__module__, self.__class__.__name__, self.name, self.type, self.occur, id(self))
|
30
|
+
|
31
|
+
@property
|
32
|
+
def name(self):
|
33
|
+
_assertValidDTDNode(self, self._c_node)
|
34
|
+
return funicodeOrNone(self._c_node.name)
|
35
|
+
|
36
|
+
@property
|
37
|
+
def type(self):
|
38
|
+
_assertValidDTDNode(self, self._c_node)
|
39
|
+
cdef int type = self._c_node.type
|
40
|
+
if type == tree.XML_ELEMENT_CONTENT_PCDATA:
|
41
|
+
return "pcdata"
|
42
|
+
elif type == tree.XML_ELEMENT_CONTENT_ELEMENT:
|
43
|
+
return "element"
|
44
|
+
elif type == tree.XML_ELEMENT_CONTENT_SEQ:
|
45
|
+
return "seq"
|
46
|
+
elif type == tree.XML_ELEMENT_CONTENT_OR:
|
47
|
+
return "or"
|
48
|
+
else:
|
49
|
+
return None
|
50
|
+
|
51
|
+
@property
|
52
|
+
def occur(self):
|
53
|
+
_assertValidDTDNode(self, self._c_node)
|
54
|
+
cdef int occur = self._c_node.ocur
|
55
|
+
if occur == tree.XML_ELEMENT_CONTENT_ONCE:
|
56
|
+
return "once"
|
57
|
+
elif occur == tree.XML_ELEMENT_CONTENT_OPT:
|
58
|
+
return "opt"
|
59
|
+
elif occur == tree.XML_ELEMENT_CONTENT_MULT:
|
60
|
+
return "mult"
|
61
|
+
elif occur == tree.XML_ELEMENT_CONTENT_PLUS:
|
62
|
+
return "plus"
|
63
|
+
else:
|
64
|
+
return None
|
65
|
+
|
66
|
+
@property
|
67
|
+
def left(self):
|
68
|
+
_assertValidDTDNode(self, self._c_node)
|
69
|
+
c1 = self._c_node.c1
|
70
|
+
if c1:
|
71
|
+
node = <_DTDElementContentDecl>_DTDElementContentDecl.__new__(_DTDElementContentDecl)
|
72
|
+
node._dtd = self._dtd
|
73
|
+
node._c_node = <tree.xmlElementContent*>c1
|
74
|
+
return node
|
75
|
+
else:
|
76
|
+
return None
|
77
|
+
|
78
|
+
@property
|
79
|
+
def right(self):
|
80
|
+
_assertValidDTDNode(self, self._c_node)
|
81
|
+
c2 = self._c_node.c2
|
82
|
+
if c2:
|
83
|
+
node = <_DTDElementContentDecl>_DTDElementContentDecl.__new__(_DTDElementContentDecl)
|
84
|
+
node._dtd = self._dtd
|
85
|
+
node._c_node = <tree.xmlElementContent*>c2
|
86
|
+
return node
|
87
|
+
else:
|
88
|
+
return None
|
89
|
+
|
90
|
+
|
91
|
+
@cython.final
|
92
|
+
@cython.internal
|
93
|
+
@cython.freelist(8)
|
94
|
+
cdef class _DTDAttributeDecl:
|
95
|
+
cdef DTD _dtd
|
96
|
+
cdef tree.xmlAttribute* _c_node
|
97
|
+
|
98
|
+
def __repr__(self):
|
99
|
+
return "<%s.%s object name=%r elemname=%r prefix=%r type=%r default=%r default_value=%r at 0x%x>" % (self.__class__.__module__, self.__class__.__name__, self.name, self.elemname, self.prefix, self.type, self.default, self.default_value, id(self))
|
100
|
+
|
101
|
+
@property
|
102
|
+
def name(self):
|
103
|
+
_assertValidDTDNode(self, self._c_node)
|
104
|
+
return funicodeOrNone(self._c_node.name)
|
105
|
+
|
106
|
+
@property
|
107
|
+
def elemname(self):
|
108
|
+
_assertValidDTDNode(self, self._c_node)
|
109
|
+
return funicodeOrNone(self._c_node.elem)
|
110
|
+
|
111
|
+
@property
|
112
|
+
def prefix(self):
|
113
|
+
_assertValidDTDNode(self, self._c_node)
|
114
|
+
return funicodeOrNone(self._c_node.prefix)
|
115
|
+
|
116
|
+
@property
|
117
|
+
def type(self):
|
118
|
+
_assertValidDTDNode(self, self._c_node)
|
119
|
+
cdef int type = self._c_node.atype
|
120
|
+
if type == tree.XML_ATTRIBUTE_CDATA:
|
121
|
+
return "cdata"
|
122
|
+
elif type == tree.XML_ATTRIBUTE_ID:
|
123
|
+
return "id"
|
124
|
+
elif type == tree.XML_ATTRIBUTE_IDREF:
|
125
|
+
return "idref"
|
126
|
+
elif type == tree.XML_ATTRIBUTE_IDREFS:
|
127
|
+
return "idrefs"
|
128
|
+
elif type == tree.XML_ATTRIBUTE_ENTITY:
|
129
|
+
return "entity"
|
130
|
+
elif type == tree.XML_ATTRIBUTE_ENTITIES:
|
131
|
+
return "entities"
|
132
|
+
elif type == tree.XML_ATTRIBUTE_NMTOKEN:
|
133
|
+
return "nmtoken"
|
134
|
+
elif type == tree.XML_ATTRIBUTE_NMTOKENS:
|
135
|
+
return "nmtokens"
|
136
|
+
elif type == tree.XML_ATTRIBUTE_ENUMERATION:
|
137
|
+
return "enumeration"
|
138
|
+
elif type == tree.XML_ATTRIBUTE_NOTATION:
|
139
|
+
return "notation"
|
140
|
+
else:
|
141
|
+
return None
|
142
|
+
|
143
|
+
@property
|
144
|
+
def default(self):
|
145
|
+
_assertValidDTDNode(self, self._c_node)
|
146
|
+
cdef int default = self._c_node.def_
|
147
|
+
if default == tree.XML_ATTRIBUTE_NONE:
|
148
|
+
return "none"
|
149
|
+
elif default == tree.XML_ATTRIBUTE_REQUIRED:
|
150
|
+
return "required"
|
151
|
+
elif default == tree.XML_ATTRIBUTE_IMPLIED:
|
152
|
+
return "implied"
|
153
|
+
elif default == tree.XML_ATTRIBUTE_FIXED:
|
154
|
+
return "fixed"
|
155
|
+
else:
|
156
|
+
return None
|
157
|
+
|
158
|
+
@property
|
159
|
+
def default_value(self):
|
160
|
+
_assertValidDTDNode(self, self._c_node)
|
161
|
+
return funicodeOrNone(self._c_node.defaultValue)
|
162
|
+
|
163
|
+
def itervalues(self):
|
164
|
+
_assertValidDTDNode(self, self._c_node)
|
165
|
+
cdef tree.xmlEnumeration *c_node = self._c_node.tree
|
166
|
+
while c_node is not NULL:
|
167
|
+
yield funicode(c_node.name)
|
168
|
+
c_node = c_node.next
|
169
|
+
|
170
|
+
def values(self):
|
171
|
+
return list(self.itervalues())
|
172
|
+
|
173
|
+
|
174
|
+
@cython.final
|
175
|
+
@cython.internal
|
176
|
+
@cython.freelist(8)
|
177
|
+
cdef class _DTDElementDecl:
|
178
|
+
cdef DTD _dtd
|
179
|
+
cdef tree.xmlElement* _c_node
|
180
|
+
|
181
|
+
def __repr__(self):
|
182
|
+
return "<%s.%s object name=%r prefix=%r type=%r at 0x%x>" % (self.__class__.__module__, self.__class__.__name__, self.name, self.prefix, self.type, id(self))
|
183
|
+
|
184
|
+
@property
|
185
|
+
def name(self):
|
186
|
+
_assertValidDTDNode(self, self._c_node)
|
187
|
+
return funicodeOrNone(self._c_node.name)
|
188
|
+
|
189
|
+
@property
|
190
|
+
def prefix(self):
|
191
|
+
_assertValidDTDNode(self, self._c_node)
|
192
|
+
return funicodeOrNone(self._c_node.prefix)
|
193
|
+
|
194
|
+
@property
|
195
|
+
def type(self):
|
196
|
+
_assertValidDTDNode(self, self._c_node)
|
197
|
+
cdef int type = self._c_node.etype
|
198
|
+
if type == tree.XML_ELEMENT_TYPE_UNDEFINED:
|
199
|
+
return "undefined"
|
200
|
+
elif type == tree.XML_ELEMENT_TYPE_EMPTY:
|
201
|
+
return "empty"
|
202
|
+
elif type == tree.XML_ELEMENT_TYPE_ANY:
|
203
|
+
return "any"
|
204
|
+
elif type == tree.XML_ELEMENT_TYPE_MIXED:
|
205
|
+
return "mixed"
|
206
|
+
elif type == tree.XML_ELEMENT_TYPE_ELEMENT:
|
207
|
+
return "element"
|
208
|
+
else:
|
209
|
+
return None
|
210
|
+
|
211
|
+
@property
|
212
|
+
def content(self):
|
213
|
+
_assertValidDTDNode(self, self._c_node)
|
214
|
+
cdef tree.xmlElementContent *content = self._c_node.content
|
215
|
+
if content:
|
216
|
+
node = <_DTDElementContentDecl>_DTDElementContentDecl.__new__(_DTDElementContentDecl)
|
217
|
+
node._dtd = self._dtd
|
218
|
+
node._c_node = content
|
219
|
+
return node
|
220
|
+
else:
|
221
|
+
return None
|
222
|
+
|
223
|
+
def iterattributes(self):
|
224
|
+
_assertValidDTDNode(self, self._c_node)
|
225
|
+
cdef tree.xmlAttribute *c_node = self._c_node.attributes
|
226
|
+
while c_node:
|
227
|
+
node = <_DTDAttributeDecl>_DTDAttributeDecl.__new__(_DTDAttributeDecl)
|
228
|
+
node._dtd = self._dtd
|
229
|
+
node._c_node = c_node
|
230
|
+
yield node
|
231
|
+
c_node = c_node.nexth
|
232
|
+
|
233
|
+
def attributes(self):
|
234
|
+
return list(self.iterattributes())
|
235
|
+
|
236
|
+
|
237
|
+
@cython.final
|
238
|
+
@cython.internal
|
239
|
+
@cython.freelist(8)
|
240
|
+
cdef class _DTDEntityDecl:
|
241
|
+
cdef DTD _dtd
|
242
|
+
cdef tree.xmlEntity* _c_node
|
243
|
+
def __repr__(self):
|
244
|
+
return "<%s.%s object name=%r at 0x%x>" % (self.__class__.__module__, self.__class__.__name__, self.name, id(self))
|
245
|
+
|
246
|
+
@property
|
247
|
+
def name(self):
|
248
|
+
_assertValidDTDNode(self, self._c_node)
|
249
|
+
return funicodeOrNone(self._c_node.name)
|
250
|
+
|
251
|
+
@property
|
252
|
+
def orig(self):
|
253
|
+
_assertValidDTDNode(self, self._c_node)
|
254
|
+
return funicodeOrNone(self._c_node.orig)
|
255
|
+
|
256
|
+
@property
|
257
|
+
def content(self):
|
258
|
+
_assertValidDTDNode(self, self._c_node)
|
259
|
+
return funicodeOrNone(self._c_node.content)
|
260
|
+
|
261
|
+
@property
|
262
|
+
def system_url(self):
|
263
|
+
_assertValidDTDNode(self, self._c_node)
|
264
|
+
return funicodeOrNone(self._c_node.SystemID)
|
265
|
+
|
266
|
+
|
267
|
+
################################################################################
|
268
|
+
# DTD
|
269
|
+
|
270
|
+
cdef class DTD(_Validator):
|
271
|
+
"""DTD(self, file=None, external_id=None)
|
272
|
+
A DTD validator.
|
273
|
+
|
274
|
+
Can load from filesystem directly given a filename or file-like object.
|
275
|
+
Alternatively, pass the keyword parameter ``external_id`` to load from a
|
276
|
+
catalog.
|
277
|
+
"""
|
278
|
+
cdef tree.xmlDtd* _c_dtd
|
279
|
+
def __init__(self, file=None, *, external_id=None):
|
280
|
+
_Validator.__init__(self)
|
281
|
+
if file is not None:
|
282
|
+
file = _getFSPathOrObject(file)
|
283
|
+
if _isString(file):
|
284
|
+
file = _encodeFilename(file)
|
285
|
+
with self._error_log:
|
286
|
+
orig_loader = _register_document_loader()
|
287
|
+
self._c_dtd = xmlparser.xmlParseDTD(NULL, _xcstr(file))
|
288
|
+
_reset_document_loader(orig_loader)
|
289
|
+
elif hasattr(file, 'read'):
|
290
|
+
orig_loader = _register_document_loader()
|
291
|
+
self._c_dtd = _parseDtdFromFilelike(file)
|
292
|
+
_reset_document_loader(orig_loader)
|
293
|
+
else:
|
294
|
+
raise DTDParseError, "file must be a filename, file-like or path-like object"
|
295
|
+
elif external_id is not None:
|
296
|
+
external_id_utf = _utf8(external_id)
|
297
|
+
with self._error_log:
|
298
|
+
orig_loader = _register_document_loader()
|
299
|
+
self._c_dtd = xmlparser.xmlParseDTD(<const_xmlChar*>external_id_utf, NULL)
|
300
|
+
_reset_document_loader(orig_loader)
|
301
|
+
else:
|
302
|
+
raise DTDParseError, "either filename or external ID required"
|
303
|
+
|
304
|
+
if self._c_dtd is NULL:
|
305
|
+
raise DTDParseError(
|
306
|
+
self._error_log._buildExceptionMessage("error parsing DTD"),
|
307
|
+
self._error_log)
|
308
|
+
|
309
|
+
@property
|
310
|
+
def name(self):
|
311
|
+
if self._c_dtd is NULL:
|
312
|
+
return None
|
313
|
+
return funicodeOrNone(self._c_dtd.name)
|
314
|
+
|
315
|
+
@property
|
316
|
+
def external_id(self):
|
317
|
+
if self._c_dtd is NULL:
|
318
|
+
return None
|
319
|
+
return funicodeOrNone(self._c_dtd.ExternalID)
|
320
|
+
|
321
|
+
@property
|
322
|
+
def system_url(self):
|
323
|
+
if self._c_dtd is NULL:
|
324
|
+
return None
|
325
|
+
return funicodeOrNone(self._c_dtd.SystemID)
|
326
|
+
|
327
|
+
def iterelements(self):
|
328
|
+
cdef tree.xmlNode *c_node = self._c_dtd.children if self._c_dtd is not NULL else NULL
|
329
|
+
while c_node is not NULL:
|
330
|
+
if c_node.type == tree.XML_ELEMENT_DECL:
|
331
|
+
node = _DTDElementDecl()
|
332
|
+
node._dtd = self
|
333
|
+
node._c_node = <tree.xmlElement*>c_node
|
334
|
+
yield node
|
335
|
+
c_node = c_node.next
|
336
|
+
|
337
|
+
def elements(self):
|
338
|
+
return list(self.iterelements())
|
339
|
+
|
340
|
+
def iterentities(self):
|
341
|
+
cdef tree.xmlNode *c_node = self._c_dtd.children if self._c_dtd is not NULL else NULL
|
342
|
+
while c_node is not NULL:
|
343
|
+
if c_node.type == tree.XML_ENTITY_DECL:
|
344
|
+
node = _DTDEntityDecl()
|
345
|
+
node._dtd = self
|
346
|
+
node._c_node = <tree.xmlEntity*>c_node
|
347
|
+
yield node
|
348
|
+
c_node = c_node.next
|
349
|
+
|
350
|
+
def entities(self):
|
351
|
+
return list(self.iterentities())
|
352
|
+
|
353
|
+
def __dealloc__(self):
|
354
|
+
tree.xmlFreeDtd(self._c_dtd)
|
355
|
+
|
356
|
+
def __call__(self, etree):
|
357
|
+
"""__call__(self, etree)
|
358
|
+
|
359
|
+
Validate doc using the DTD.
|
360
|
+
|
361
|
+
Returns true if the document is valid, false if not.
|
362
|
+
"""
|
363
|
+
cdef _Document doc
|
364
|
+
cdef _Element root_node
|
365
|
+
cdef xmlDoc* c_doc
|
366
|
+
cdef dtdvalid.xmlValidCtxt* valid_ctxt
|
367
|
+
cdef int ret = -1
|
368
|
+
|
369
|
+
assert self._c_dtd is not NULL, "DTD not initialised"
|
370
|
+
doc = _documentOrRaise(etree)
|
371
|
+
root_node = _rootNodeOrRaise(etree)
|
372
|
+
|
373
|
+
valid_ctxt = dtdvalid.xmlNewValidCtxt()
|
374
|
+
if valid_ctxt is NULL:
|
375
|
+
raise DTDError("Failed to create validation context")
|
376
|
+
|
377
|
+
# work around error reporting bug in libxml2 <= 2.9.1 (and later?)
|
378
|
+
# https://bugzilla.gnome.org/show_bug.cgi?id=724903
|
379
|
+
valid_ctxt.error = <dtdvalid.xmlValidityErrorFunc>_nullGenericErrorFunc
|
380
|
+
valid_ctxt.userData = NULL
|
381
|
+
|
382
|
+
try:
|
383
|
+
with self._error_log:
|
384
|
+
c_doc = _fakeRootDoc(doc._c_doc, root_node._c_node)
|
385
|
+
ret = dtdvalid.xmlValidateDtd(valid_ctxt, c_doc, self._c_dtd)
|
386
|
+
_destroyFakeDoc(doc._c_doc, c_doc)
|
387
|
+
finally:
|
388
|
+
dtdvalid.xmlFreeValidCtxt(valid_ctxt)
|
389
|
+
|
390
|
+
if ret == -1:
|
391
|
+
raise DTDValidateError("Internal error in DTD validation",
|
392
|
+
self._error_log)
|
393
|
+
return ret == 1
|
394
|
+
|
395
|
+
|
396
|
+
cdef tree.xmlDtd* _parseDtdFromFilelike(file) except NULL:
|
397
|
+
cdef _ExceptionContext exc_context
|
398
|
+
cdef _FileReaderContext dtd_parser
|
399
|
+
cdef _ErrorLog error_log
|
400
|
+
cdef tree.xmlDtd* c_dtd = NULL
|
401
|
+
exc_context = _ExceptionContext()
|
402
|
+
dtd_parser = _FileReaderContext(file, exc_context, None)
|
403
|
+
error_log = _ErrorLog()
|
404
|
+
|
405
|
+
with error_log:
|
406
|
+
c_dtd = dtd_parser._readDtd()
|
407
|
+
|
408
|
+
exc_context._raise_if_stored()
|
409
|
+
if c_dtd is NULL:
|
410
|
+
raise DTDParseError("error parsing DTD", error_log)
|
411
|
+
return c_dtd
|
412
|
+
|
413
|
+
cdef DTD _dtdFactory(tree.xmlDtd* c_dtd):
|
414
|
+
# do not run through DTD.__init__()!
|
415
|
+
cdef DTD dtd
|
416
|
+
if c_dtd is NULL:
|
417
|
+
return None
|
418
|
+
dtd = DTD.__new__(DTD)
|
419
|
+
dtd._c_dtd = _copyDtd(c_dtd)
|
420
|
+
_Validator.__init__(dtd)
|
421
|
+
return dtd
|
422
|
+
|
423
|
+
|
424
|
+
cdef tree.xmlDtd* _copyDtd(tree.xmlDtd* c_orig_dtd) except NULL:
|
425
|
+
"""
|
426
|
+
Copy a DTD. libxml2 (currently) fails to set up the element->attributes
|
427
|
+
links when copying DTDs, so we have to rebuild them here.
|
428
|
+
"""
|
429
|
+
c_dtd = tree.xmlCopyDtd(c_orig_dtd)
|
430
|
+
if not c_dtd:
|
431
|
+
raise MemoryError
|
432
|
+
cdef tree.xmlNode* c_node = c_dtd.children
|
433
|
+
while c_node:
|
434
|
+
if c_node.type == tree.XML_ATTRIBUTE_DECL:
|
435
|
+
_linkDtdAttribute(c_dtd, <tree.xmlAttribute*>c_node)
|
436
|
+
c_node = c_node.next
|
437
|
+
return c_dtd
|
438
|
+
|
439
|
+
|
440
|
+
cdef void _linkDtdAttribute(tree.xmlDtd* c_dtd, tree.xmlAttribute* c_attr) noexcept:
|
441
|
+
"""
|
442
|
+
Create the link to the DTD attribute declaration from the corresponding
|
443
|
+
element declaration.
|
444
|
+
"""
|
445
|
+
c_elem = dtdvalid.xmlGetDtdElementDesc(c_dtd, c_attr.elem)
|
446
|
+
if not c_elem:
|
447
|
+
# no such element? something is wrong with the DTD ...
|
448
|
+
return
|
449
|
+
c_pos = c_elem.attributes
|
450
|
+
if not c_pos:
|
451
|
+
c_elem.attributes = c_attr
|
452
|
+
c_attr.nexth = NULL
|
453
|
+
return
|
454
|
+
# libxml2 keeps namespace declarations first, and we need to make
|
455
|
+
# sure we don't re-insert attributes that are already there
|
456
|
+
if _isDtdNsDecl(c_attr):
|
457
|
+
if not _isDtdNsDecl(c_pos):
|
458
|
+
c_elem.attributes = c_attr
|
459
|
+
c_attr.nexth = c_pos
|
460
|
+
return
|
461
|
+
while c_pos != c_attr and c_pos.nexth and _isDtdNsDecl(c_pos.nexth):
|
462
|
+
c_pos = c_pos.nexth
|
463
|
+
else:
|
464
|
+
# append at end
|
465
|
+
while c_pos != c_attr and c_pos.nexth:
|
466
|
+
c_pos = c_pos.nexth
|
467
|
+
if c_pos == c_attr:
|
468
|
+
return
|
469
|
+
c_attr.nexth = c_pos.nexth
|
470
|
+
c_pos.nexth = c_attr
|
471
|
+
|
472
|
+
|
473
|
+
cdef bint _isDtdNsDecl(tree.xmlAttribute* c_attr) noexcept:
|
474
|
+
if cstring_h.strcmp(<const_char*>c_attr.name, "xmlns") == 0:
|
475
|
+
return True
|
476
|
+
if (c_attr.prefix is not NULL and
|
477
|
+
cstring_h.strcmp(<const_char*>c_attr.prefix, "xmlns") == 0):
|
478
|
+
return True
|
479
|
+
return False
|
Binary file
|