1#!/usr/bin/python -u
2#
3# this tests the DTD validation with the XmlTextReader interface
4#
5import sys
6import glob
7import string
8import libxml2
9try:
10    import StringIO
11    str_io = StringIO.StringIO
12except:
13    import io
14    str_io = io.StringIO
15
16# Memory debug specific
17libxml2.debugMemory(1)
18
19err=""
20expect="""../../test/valid/rss.xml:177: element rss: validity error : Element rss does not carry attribute version
21</rss>
22      ^
23../../test/valid/xlink.xml:450: element termdef: validity error : ID dt-arc already defined
24	<p><termdef id="dt-arc" term="Arc">An <ter
25	                                  ^
26../../test/valid/xlink.xml:530: validity error : attribute def line 199 references an unknown ID "dt-xlg"
27
28^
29"""
30def callback(ctx, str):
31    global err
32    err = err + "%s" % (str)
33libxml2.registerErrorHandler(callback, "")
34
35valid_files = glob.glob("../../test/valid/*.x*")
36valid_files.sort()
37for file in valid_files:
38    if file.find("t8") != -1:
39        continue
40    if file == "../../test/valid/rss.xml":
41        continue
42    if file == "../../test/valid/xlink.xml":
43        continue
44    reader = libxml2.newTextReaderFilename(file)
45    #print "%s:" % (file)
46    reader.SetParserProp(libxml2.PARSER_VALIDATE, 1)
47    ret = reader.Read()
48    while ret == 1:
49        ret = reader.Read()
50    if ret != 0:
51        print("Error parsing and validating %s" % (file))
52	#sys.exit(1)
53
54if err != expect:
55    print(err)
56
57#
58# another separate test based on Stephane Bidoul one
59#
60s = """
61<!DOCTYPE test [
62<!ELEMENT test (x,b)>
63<!ELEMENT x (c)>
64<!ELEMENT b (#PCDATA)>
65<!ELEMENT c (#PCDATA)>
66<!ENTITY x "<x><c>xxx</c></x>">
67]>
68<test>
69    &x;
70    <b>bbb</b>
71</test>
72"""
73expect="""10,test
741,test
7514,#text
761,x
771,c
783,#text
7915,c
8015,x
8114,#text
821,b
833,#text
8415,b
8514,#text
8615,test
87"""
88res=""
89err=""
90
91input = libxml2.inputBuffer(str_io(s))
92reader = input.newTextReader("test2")
93reader.SetParserProp(libxml2.PARSER_LOADDTD,1)
94reader.SetParserProp(libxml2.PARSER_DEFAULTATTRS,1)
95reader.SetParserProp(libxml2.PARSER_SUBST_ENTITIES,1)
96reader.SetParserProp(libxml2.PARSER_VALIDATE,1)
97while reader.Read() == 1:
98    res = res + "%s,%s\n" % (reader.NodeType(),reader.Name())
99
100if res != expect:
101    print("test2 failed: unexpected output")
102    print(res)
103    sys.exit(1)
104if err != "":
105    print("test2 failed: validation error found")
106    print(err)
107    sys.exit(1)
108
109#
110# Another test for external entity parsing and validation
111#
112
113s = """<!DOCTYPE test [
114<!ELEMENT test (x)>
115<!ELEMENT x (#PCDATA)>
116<!ENTITY e SYSTEM "tst.ent">
117]>
118<test>
119  &e;
120</test>
121"""
122tst_ent = """<x>hello</x>"""
123expect="""10 test
1241 test
12514 #text
1261 x
1273 #text
12815 x
12914 #text
13015 test
131"""
132res=""
133
134def myResolver(URL, ID, ctxt):
135    if URL == "tst.ent":
136        return(str_io(tst_ent))
137    return None
138
139libxml2.setEntityLoader(myResolver)
140
141input = libxml2.inputBuffer(str_io(s))
142reader = input.newTextReader("test3")
143reader.SetParserProp(libxml2.PARSER_LOADDTD,1)
144reader.SetParserProp(libxml2.PARSER_DEFAULTATTRS,1)
145reader.SetParserProp(libxml2.PARSER_SUBST_ENTITIES,1)
146reader.SetParserProp(libxml2.PARSER_VALIDATE,1)
147while reader.Read() == 1:
148    res = res + "%s %s\n" % (reader.NodeType(),reader.Name())
149
150if res != expect:
151    print("test3 failed: unexpected output")
152    print(res)
153    sys.exit(1)
154if err != "":
155    print("test3 failed: validation error found")
156    print(err)
157    sys.exit(1)
158
159#
160# Another test for recursive entity parsing, validation, and replacement of
161# entities, making sure the entity ref node doesn't show up in that case
162#
163
164s = """<!DOCTYPE test [
165<!ELEMENT test (x, x)>
166<!ELEMENT x (y)>
167<!ELEMENT y (#PCDATA)>
168<!ENTITY x "<x>&y;</x>">
169<!ENTITY y "<y>yyy</y>">
170]>
171<test>
172  &x;
173  &x;
174</test>"""
175expect="""10 test 0
1761 test 0
17714 #text 1
1781 x 1
1791 y 2
1803 #text 3
18115 y 2
18215 x 1
18314 #text 1
1841 x 1
1851 y 2
1863 #text 3
18715 y 2
18815 x 1
18914 #text 1
19015 test 0
191"""
192res=""
193err=""
194
195input = libxml2.inputBuffer(str_io(s))
196reader = input.newTextReader("test4")
197reader.SetParserProp(libxml2.PARSER_LOADDTD,1)
198reader.SetParserProp(libxml2.PARSER_DEFAULTATTRS,1)
199reader.SetParserProp(libxml2.PARSER_SUBST_ENTITIES,1)
200reader.SetParserProp(libxml2.PARSER_VALIDATE,1)
201while reader.Read() == 1:
202    res = res + "%s %s %d\n" % (reader.NodeType(),reader.Name(),reader.Depth())
203
204if res != expect:
205    print("test4 failed: unexpected output")
206    print(res)
207    sys.exit(1)
208if err != "":
209    print("test4 failed: validation error found")
210    print(err)
211    sys.exit(1)
212
213#
214# The same test but without entity substitution this time
215#
216
217s = """<!DOCTYPE test [
218<!ELEMENT test (x, x)>
219<!ELEMENT x (y)>
220<!ELEMENT y (#PCDATA)>
221<!ENTITY x "<x>&y;</x>">
222<!ENTITY y "<y>yyy</y>">
223]>
224<test>
225  &x;
226  &x;
227</test>"""
228expect="""10 test 0
2291 test 0
23014 #text 1
2315 x 1
23214 #text 1
2335 x 1
23414 #text 1
23515 test 0
236"""
237res=""
238err=""
239
240input = libxml2.inputBuffer(str_io(s))
241reader = input.newTextReader("test5")
242reader.SetParserProp(libxml2.PARSER_VALIDATE,1)
243while reader.Read() == 1:
244    res = res + "%s %s %d\n" % (reader.NodeType(),reader.Name(),reader.Depth())
245
246if res != expect:
247    print("test5 failed: unexpected output")
248    print(res)
249if err != "":
250    print("test5 failed: validation error found")
251    print(err)
252
253#
254# cleanup
255#
256del input
257del reader
258
259# Memory debug specific
260libxml2.cleanupParser()
261if libxml2.debugMemory(1) == 0:
262    print("OK")
263else:
264    print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
265    libxml2.dumpMemory()
266