1
2
3 """
4 Test cases related to XSLT processing
5 """
6
7 import unittest, copy, sys, os.path
8
9 this_dir = os.path.dirname(__file__)
10 if this_dir not in sys.path:
11 sys.path.insert(0, this_dir)
12
13 is_python3 = sys.version_info[0] >= 3
14
15 try:
16 unicode = __builtins__["unicode"]
17 except (NameError, KeyError):
18 unicode = str
19
20 try:
21 basestring = __builtins__["basestring"]
22 except (NameError, KeyError):
23 basestring = str
24
25 from common_imports import etree, BytesIO, HelperTestCase, fileInTestDir
26 from common_imports import doctest, _bytes, _str, make_doctest
27
29 """XSLT tests etree"""
30
32 tree = self.parse('<a><b>B</b><c>C</c></a>')
33 style = self.parse('''\
34 <xsl:stylesheet version="1.0"
35 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
36 <xsl:template match="*" />
37 <xsl:template match="/">
38 <foo><xsl:value-of select="/a/b/text()" /></foo>
39 </xsl:template>
40 </xsl:stylesheet>''')
41
42 st = etree.XSLT(style)
43 res = st(tree)
44 self.assertEquals('''\
45 <?xml version="1.0"?>
46 <foo>B</foo>
47 ''',
48 str(res))
49
52
55
56 if False and etree.LIBXSLT_VERSION >= (1,1,15):
57
58 if etree.LIBXSLT_VERSION > (1,1,17):
60 style = self.parse('''\
61 <xsl:stylesheet version="1.0"
62 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
63 <xsl:stylesheet />
64 </xsl:stylesheet>''')
65
66 self.assertRaises(
67 etree.XSLTParseError, etree.XSLT, style)
68
70 tree = self.parse('<a><b>B</b><c>C</c></a>')
71 style = self.parse('''\
72 <xsl:stylesheet version="1.0"
73 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
74 <xsl:template match="*" />
75 <xsl:template match="/">
76 <foo><xsl:value-of select="/a/b/text()" /></foo>
77 </xsl:template>
78 </xsl:stylesheet>''')
79
80 transform = etree.XSLT(style)
81 res = transform(tree)
82 self.assertEquals('''\
83 <?xml version="1.0"?>
84 <foo>B</foo>
85 ''',
86 str(res))
87
88 transform_copy = copy.deepcopy(transform)
89 res = transform_copy(tree)
90 self.assertEquals('''\
91 <?xml version="1.0"?>
92 <foo>B</foo>
93 ''',
94 str(res))
95
96 transform = etree.XSLT(style)
97 res = transform(tree)
98 self.assertEquals('''\
99 <?xml version="1.0"?>
100 <foo>B</foo>
101 ''',
102 str(res))
103
105 tree = self.parse(_bytes('<a><b>\\uF8D2</b><c>\\uF8D2</c></a>'
106 ).decode("unicode_escape"))
107 style = self.parse('''\
108 <xsl:stylesheet version="1.0"
109 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
110 <xsl:output encoding="UTF-8"/>
111 <xsl:template match="/">
112 <foo><xsl:value-of select="/a/b/text()" /></foo>
113 </xsl:template>
114 </xsl:stylesheet>''')
115
116 st = etree.XSLT(style)
117 res = st(tree)
118 expected = _bytes('''\
119 <?xml version="1.0" encoding="UTF-8"?>
120 <foo>\\uF8D2</foo>
121 ''').decode("unicode_escape")
122 if is_python3:
123 self.assertEquals(expected,
124 str(bytes(res), 'UTF-8'))
125 else:
126 self.assertEquals(expected,
127 unicode(str(res), 'UTF-8'))
128
130 tree = self.parse(_bytes('<a><b>\\uF8D2</b><c>\\uF8D2</c></a>'
131 ).decode("unicode_escape"))
132 style = self.parse('''\
133 <xsl:stylesheet version="1.0"
134 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
135 <xsl:output encoding="UTF-16"/>
136 <xsl:template match="/">
137 <foo><xsl:value-of select="/a/b/text()" /></foo>
138 </xsl:template>
139 </xsl:stylesheet>''')
140
141 st = etree.XSLT(style)
142 res = st(tree)
143 expected = _bytes('''\
144 <?xml version="1.0" encoding="UTF-16"?>
145 <foo>\\uF8D2</foo>
146 ''').decode("unicode_escape")
147 if is_python3:
148 self.assertEquals(expected,
149 str(bytes(res), 'UTF-16'))
150 else:
151 self.assertEquals(expected,
152 unicode(str(res), 'UTF-16'))
153
155 tree = self.parse(_bytes('<a><b>\\uF8D2</b><c>\\uF8D2</c></a>'
156 ).decode("unicode_escape"))
157 style = self.parse('''\
158 <xsl:stylesheet version="1.0"
159 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
160 <xsl:output encoding="UTF-8"/>
161 <xsl:template match="/">
162 <foo><xsl:value-of select="/a/b/text()" /></foo>
163 </xsl:template>
164 </xsl:stylesheet>''')
165
166 st = etree.XSLT(style)
167 res = st(tree)
168 expected = _bytes("""\
169 <?xml version='1.0' encoding='UTF-16'?>\
170 <foo>\\uF8D2</foo>""").decode("unicode_escape")
171
172 f = BytesIO()
173 res.write(f, encoding='UTF-16')
174 if is_python3:
175 result = str(f.getvalue(), 'UTF-16').replace('\n', '')
176 else:
177 result = unicode(str(f.getvalue()), 'UTF-16').replace('\n', '')
178 self.assertEquals(expected, result)
179
181 tree = self.parse(_bytes('<a><b>\\uF8D2</b><c>\\uF8D2</c></a>'
182 ).decode("unicode_escape"))
183 style = self.parse('''\
184 <xsl:stylesheet version="1.0"
185 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
186 <xsl:output encoding="UTF-16"/>
187 <xsl:template match="/">
188 <foo><xsl:value-of select="/a/b/text()" /></foo>
189 </xsl:template>
190 </xsl:stylesheet>''')
191
192 st = etree.XSLT(style)
193 res = st(tree)
194 expected = _bytes('''\
195 <?xml version="1.0"?>
196 <foo>\\uF8D2</foo>
197 ''').decode("unicode_escape")
198 self.assertEquals(expected,
199 unicode(res))
200
202 tree = self.parse('<a><b>B</b><c>C</c></a>')
203 style = self.parse('''\
204 <xsl:stylesheet version="1.0"
205 xmlns:str="http://exslt.org/strings"
206 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
207 exclude-result-prefixes="str xsl">
208 <xsl:template match="text()">
209 <xsl:value-of select="str:align(string(.), '***', 'center')" />
210 </xsl:template>
211 <xsl:template match="*">
212 <xsl:copy>
213 <xsl:apply-templates/>
214 </xsl:copy>
215 </xsl:template>
216 </xsl:stylesheet>''')
217
218 st = etree.XSLT(style)
219 res = st(tree)
220 self.assertEquals('''\
221 <?xml version="1.0"?>
222 <a><b>*B*</b><c>*C*</c></a>
223 ''',
224 str(res))
225
226 if etree.LIBXSLT_VERSION >= (1,1,21):
228 tree = self.parse('<a><b>B</b><c>C</c></a>')
229 style = self.parse('''\
230 <xsl:stylesheet version = "1.0"
231 xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
232 xmlns:str="http://exslt.org/strings"
233 extension-element-prefixes="str">
234
235 <xsl:template match="/">
236 <h1 class="{str:replace('abc', 'b', 'x')}">test</h1>
237 </xsl:template>
238
239 </xsl:stylesheet>''')
240
241 st = etree.XSLT(style)
242 res = st(tree)
243 self.assertEquals('''\
244 <?xml version="1.0"?>
245 <h1 class="axc">test</h1>
246 ''',
247 str(res))
248
250 tree = self.parse('<a><b>B</b><c>C</c></a>')
251 style = self.parse('''\
252 <xsl:stylesheet version="1.0"
253 xmlns:math="http://exslt.org/math"
254 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
255 exclude-result-prefixes="math xsl">
256 <xsl:template match="*">
257 <xsl:copy>
258 <xsl:attribute name="pi">
259 <xsl:value-of select="math:constant('PI', count(*)+2)"/>
260 </xsl:attribute>
261 <xsl:apply-templates/>
262 </xsl:copy>
263 </xsl:template>
264 </xsl:stylesheet>''')
265
266 st = etree.XSLT(style)
267 res = st(tree)
268 self.assertEquals('''\
269 <?xml version="1.0"?>
270 <a pi="3.14"><b pi="3">B</b><c pi="3">C</c></a>
271 ''',
272 str(res))
273
286
303
305 tree = self.parse('<a/>')
306 style = self.parse('''\
307 <xsl:stylesheet version="1.0"
308 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
309 <xsl:foo />
310 </xsl:stylesheet>''')
311 self.assertRaises(etree.XSLTParseError,
312 etree.XSLT, style)
313
315 tree = self.parse('<a><b>B</b><c>C</c></a>')
316 style = self.parse('''\
317 <xsl:stylesheet version="1.0"
318 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
319 <xsl:template match="/">
320 <foo><xsl:value-of select="$bar" /></foo>
321 </xsl:template>
322 </xsl:stylesheet>''')
323
324 st = etree.XSLT(style)
325 res = st(tree, bar="'Bar'")
326 self.assertEquals('''\
327 <?xml version="1.0"?>
328 <foo>Bar</foo>
329 ''',
330 str(res))
331
333 tree = self.parse('<a><b>B</b><c>C</c></a>')
334 style = self.parse('''\
335 <xsl:stylesheet version="1.0"
336 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
337 <xsl:template match="/">
338 <foo><xsl:value-of select="$bar" /></foo>
339 </xsl:template>
340 </xsl:stylesheet>''')
341
342 st = etree.XSLT(style)
343 res = st(tree, bar=etree.XSLT.strparam('''it's me, "Bar"'''))
344 self.assertEquals('''\
345 <?xml version="1.0"?>
346 <foo>it's me, "Bar"</foo>
347 ''',
348 str(res))
349
351 tree = self.parse('<a><b>B</b><c>C</c></a>')
352 style = self.parse('''\
353 <xsl:stylesheet version="1.0"
354 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
355 <xsl:param name="bar"/>
356 <xsl:template match="/">
357 <foo><xsl:value-of select="$bar" /></foo>
358 </xsl:template>
359 </xsl:stylesheet>''')
360
361 st = etree.XSLT(style)
362 res = self.assertRaises(etree.XSLTApplyError,
363 st, tree, bar="<test/>")
364 res = self.assertRaises(etree.XSLTApplyError,
365 st, tree, bar="....")
366
367 if etree.LIBXSLT_VERSION < (1,1,18):
368
370
371 tree = self.parse('<a><b>B</b><c>C</c></a>')
372 style = self.parse('''\
373 <xsl:stylesheet version="1.0"
374 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
375 <xsl:template match="/">
376 <foo><xsl:value-of select="$bar" /></foo>
377 </xsl:template>
378 </xsl:stylesheet>''')
379
380 st = etree.XSLT(style)
381 self.assertRaises(etree.XSLTApplyError,
382 st.apply, tree)
383
385 tree = self.parse('<a><b>B</b><c>C</c></a>')
386 style = self.parse('''\
387 <xsl:stylesheet version="1.0"
388 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
389 <xsl:template match="*" />
390 <xsl:template match="/">
391 <foo><xsl:value-of select="$bar" /></foo>
392 <foo><xsl:value-of select="$baz" /></foo>
393 </xsl:template>
394 </xsl:stylesheet>''')
395
396 st = etree.XSLT(style)
397 res = st(tree, bar="'Bar'", baz="'Baz'")
398 self.assertEquals('''\
399 <?xml version="1.0"?>
400 <foo>Bar</foo><foo>Baz</foo>
401 ''',
402 str(res))
403
405 tree = self.parse('<a><b>B</b><c>C</c></a>')
406 style = self.parse('''\
407 <xsl:stylesheet version="1.0"
408 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
409 <xsl:template match="*" />
410 <xsl:template match="/">
411 <foo><xsl:value-of select="$bar" /></foo>
412 </xsl:template>
413 </xsl:stylesheet>''')
414
415 st = etree.XSLT(style)
416 res = st(tree, bar="/a/b/text()")
417 self.assertEquals('''\
418 <?xml version="1.0"?>
419 <foo>B</foo>
420 ''',
421 str(res))
422
423
425 tree = self.parse('<a><b>B</b><c>C</c></a>')
426 style = self.parse('''\
427 <xsl:stylesheet version="1.0"
428 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
429 <xsl:param name="bar" select="'Default'" />
430 <xsl:template match="*" />
431 <xsl:template match="/">
432 <foo><xsl:value-of select="$bar" /></foo>
433 </xsl:template>
434 </xsl:stylesheet>''')
435
436 st = etree.XSLT(style)
437 res = st(tree, bar="'Bar'")
438 self.assertEquals('''\
439 <?xml version="1.0"?>
440 <foo>Bar</foo>
441 ''',
442 str(res))
443 res = st(tree)
444 self.assertEquals('''\
445 <?xml version="1.0"?>
446 <foo>Default</foo>
447 ''',
448 str(res))
449
451 tree = self.parse('<a><b>B</b><c>C</c></a>')
452 style = self.parse('''\
453 <xsl:stylesheet version="1.0"
454 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
455 <xsl:output method="html"/>
456 <xsl:strip-space elements="*"/>
457 <xsl:template match="/">
458 <html><body><xsl:value-of select="/a/b/text()" /></body></html>
459 </xsl:template>
460 </xsl:stylesheet>''')
461
462 st = etree.XSLT(style)
463 res = st(tree)
464 self.assertEquals('<html><body>B</body></html>',
465 str(res).strip())
466
470
476
499
524
526
527 xml = '<blah/>'
528 xslt = '''
529 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
530 <xsl:template match="/" />
531 </xsl:stylesheet>
532 '''
533
534 source = self.parse(xml)
535 styledoc = self.parse(xslt)
536 style = etree.XSLT(styledoc)
537 result = style(source)
538 self.assertEqual('', str(result))
539
541 xml = '<blah/>'
542 xslt = '''
543 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
544 <xsl:template match="/">
545 <xsl:message>TEST TEST TEST</xsl:message>
546 </xsl:template>
547 </xsl:stylesheet>
548 '''
549
550 source = self.parse(xml)
551 styledoc = self.parse(xslt)
552 style = etree.XSLT(styledoc)
553 result = style(source)
554 self.assertEqual('', str(result))
555 self.assert_("TEST TEST TEST" in [entry.message
556 for entry in style.error_log])
557
559 xml = '<blah/>'
560 xslt = '''
561 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
562 <xsl:template match="/">
563 <xsl:message terminate="yes">TEST TEST TEST</xsl:message>
564 </xsl:template>
565 </xsl:stylesheet>
566 '''
567
568 source = self.parse(xml)
569 styledoc = self.parse(xslt)
570 style = etree.XSLT(styledoc)
571
572 self.assertRaises(etree.XSLTApplyError, style, source)
573 self.assert_("TEST TEST TEST" in [entry.message
574 for entry in style.error_log])
575
577 tree = self.parse('<a><b>B</b><c>C</c></a>')
578 style = self.parse('''\
579 <xsl:stylesheet version="1.0"
580 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
581 <xsl:template match="*" />
582 <xsl:template match="/">
583 <doc>
584 <foo><xsl:value-of select="$bar" /></foo>
585 <foo><xsl:value-of select="$baz" /></foo>
586 </doc>
587 </xsl:template>
588 </xsl:stylesheet>''')
589
590 result = tree.xslt(style, bar="'Bar'", baz="'Baz'")
591 self.assertEquals(
592 _bytes('<doc><foo>Bar</foo><foo>Baz</foo></doc>'),
593 etree.tostring(result.getroot()))
594
596 tree = self.parse('<a><b>B</b><c>C</c></a>')
597 style = self.parse('''\
598 <xsl:stylesheet version="1.0"
599 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
600 <xsl:template match="a"><A><xsl:apply-templates/></A></xsl:template>
601 <xsl:template match="b"><B><xsl:apply-templates/></B></xsl:template>
602 <xsl:template match="c"><C><xsl:apply-templates/></C></xsl:template>
603 </xsl:stylesheet>''')
604
605 self.assertEquals(self._rootstring(tree),
606 _bytes('<a><b>B</b><c>C</c></a>'))
607 result = tree.xslt(style)
608 self.assertEquals(self._rootstring(tree),
609 _bytes('<a><b>B</b><c>C</c></a>'))
610 self.assertEquals(self._rootstring(result),
611 _bytes('<A><B>B</B><C>C</C></A>'))
612
613 b_tree = etree.ElementTree(tree.getroot()[0])
614 self.assertEquals(self._rootstring(b_tree),
615 _bytes('<b>B</b>'))
616 result = b_tree.xslt(style)
617 self.assertEquals(self._rootstring(tree),
618 _bytes('<a><b>B</b><c>C</c></a>'))
619 self.assertEquals(self._rootstring(result),
620 _bytes('<B>B</B>'))
621
622 c_tree = etree.ElementTree(tree.getroot()[1])
623 self.assertEquals(self._rootstring(c_tree),
624 _bytes('<c>C</c>'))
625 result = c_tree.xslt(style)
626 self.assertEquals(self._rootstring(tree),
627 _bytes('<a><b>B</b><c>C</c></a>'))
628 self.assertEquals(self._rootstring(result),
629 _bytes('<C>C</C>'))
630
632 tree = self.parse('<a><b>B</b></a>')
633 style = self.parse('''\
634 <xsl:stylesheet version="1.0"
635 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
636 xmlns:myns="testns"
637 exclude-result-prefixes="myns">
638 <xsl:template match="a"><A><xsl:value-of select="myns:mytext(b)"/></A></xsl:template>
639 </xsl:stylesheet>''')
640
641 def mytext(ctxt, values):
642 return 'X' * len(values)
643
644 result = tree.xslt(style, {('testns', 'mytext') : mytext})
645 self.assertEquals(self._rootstring(result),
646 _bytes('<A>X</A>'))
647
649 tree = self.parse('<a><b>B</b></a>')
650 style = self.parse('''\
651 <xsl:stylesheet version="1.0"
652 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
653 xmlns:myns="testns"
654 exclude-result-prefixes="myns">
655 <xsl:template match="a"><A><xsl:value-of select="myns:mytext(b)"/></A></xsl:template>
656 </xsl:stylesheet>''')
657
658 def mytext(ctxt, values):
659 return 'X' * len(values)
660
661 namespace = etree.FunctionNamespace('testns')
662 namespace['mytext'] = mytext
663
664 result = tree.xslt(style)
665 self.assertEquals(self._rootstring(result),
666 _bytes('<A>X</A>'))
667
669 tree = self.parse('<a><b>B</b><b/></a>')
670 style = self.parse('''\
671 <xsl:stylesheet version="1.0"
672 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
673 xmlns:myns="testns"
674 exclude-result-prefixes="myns">
675 <xsl:template match="a">
676 <xsl:variable name="content">
677 <xsl:apply-templates/>
678 </xsl:variable>
679 <A><xsl:value-of select="myns:mytext($content)"/></A>
680 </xsl:template>
681 <xsl:template match="b"><xsl:copy>BBB</xsl:copy></xsl:template>
682 </xsl:stylesheet>''')
683
684 def mytext(ctxt, values):
685 for value in values:
686 self.assert_(hasattr(value, 'tag'),
687 "%s is not an Element" % type(value))
688 self.assertEquals(value.tag, 'b')
689 self.assertEquals(value.text, 'BBB')
690 return 'X'.join([el.tag for el in values])
691
692 namespace = etree.FunctionNamespace('testns')
693 namespace['mytext'] = mytext
694
695 result = tree.xslt(style)
696 self.assertEquals(self._rootstring(result),
697 _bytes('<A>bXb</A>'))
698
700 tree = self.parse('<a><b>B</b></a>')
701 style = self.parse('''\
702 <xsl:stylesheet version="1.0"
703 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
704 xmlns:myns="testns"
705 extension-element-prefixes="myns"
706 exclude-result-prefixes="myns">
707 <xsl:template match="a">
708 <A><myns:myext>b</myns:myext></A>
709 </xsl:template>
710 </xsl:stylesheet>''')
711
712 class MyExt(etree.XSLTExtension):
713 def execute(self, context, self_node, input_node, output_parent):
714 child = etree.Element(self_node.text)
715 child.text = 'X'
716 output_parent.append(child)
717
718 extensions = { ('testns', 'myext') : MyExt() }
719
720 result = tree.xslt(style, extensions=extensions)
721 self.assertEquals(self._rootstring(result),
722 _bytes('<A><b>X</b></A>'))
723
725 tree = self.parse('<a><b>B</b></a>')
726 style = self.parse('''\
727 <xsl:stylesheet version="1.0"
728 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
729 xmlns:myns="testns"
730 extension-element-prefixes="myns"
731 exclude-result-prefixes="myns">
732 <xsl:template match="/">
733 <A><myns:myext>b</myns:myext></A>
734 </xsl:template>
735 </xsl:stylesheet>''')
736
737 tags = []
738
739 class MyExt(etree.XSLTExtension):
740 def execute(self, context, self_node, input_node, output_parent):
741 tags.append(input_node.tag)
742
743 extensions = { ('testns', 'myext') : MyExt() }
744
745 result = tree.xslt(style, extensions=extensions)
746 self.assertEquals(tags, ['a'])
747
749 tree = self.parse('<a><!--a comment--></a>')
750 style = self.parse('''\
751 <xsl:stylesheet version="1.0"
752 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
753 xmlns:myns="testns"
754 extension-element-prefixes="myns"
755 exclude-result-prefixes="myns">
756 <xsl:template match="comment()">
757 <A><myns:myext>b</myns:myext></A>
758 </xsl:template>
759 </xsl:stylesheet>''')
760
761 tags = []
762
763 class MyExt(etree.XSLTExtension):
764 def execute(self, context, self_node, input_node, output_parent):
765 tags.append(input_node.tag)
766
767 extensions = { ('testns', 'myext') : MyExt() }
768
769 self.assertRaises(TypeError, tree.xslt, style, extensions=extensions)
770 self.assertEquals(tags, [])
771
773 tree = self.parse('<a><b>B</b></a>')
774 style = self.parse('''\
775 <xsl:stylesheet version="1.0"
776 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
777 xmlns:myns="testns"
778 extension-element-prefixes="myns">
779 <xsl:template match="a">
780 <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
781 </xsl:template>
782 </xsl:stylesheet>''')
783
784 class MyExt(etree.XSLTExtension):
785 def execute(self, context, self_node, input_node, output_parent):
786 output_parent.extend(list(self_node)[1:])
787
788 extensions = { ('testns', 'myext') : MyExt() }
789
790 result = tree.xslt(style, extensions=extensions)
791 self.assertEquals(self._rootstring(result),
792 _bytes('<A><y>Y</y><z/></A>'))
793
795 tree = self.parse('<a><b>B</b></a>')
796 style = self.parse('''\
797 <xsl:stylesheet version="1.0"
798 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
799 xmlns:myns="testns"
800 extension-element-prefixes="myns">
801 <xsl:template match="a">
802 <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
803 </xsl:template>
804 <xsl:template match="x" />
805 <xsl:template match="z">XYZ</xsl:template>
806 </xsl:stylesheet>''')
807
808 class MyExt(etree.XSLTExtension):
809 def execute(self, context, self_node, input_node, output_parent):
810 for child in self_node:
811 for result in self.apply_templates(context, child):
812 if isinstance(result, basestring):
813 el = etree.Element("T")
814 el.text = result
815 else:
816 el = result
817 output_parent.append(el)
818
819 extensions = { ('testns', 'myext') : MyExt() }
820
821 result = tree.xslt(style, extensions=extensions)
822 self.assertEquals(self._rootstring(result),
823 _bytes('<A><T>Y</T><T>XYZ</T></A>'))
824
826 tree = self.parse('<a><b>B</b></a>')
827 style = self.parse('''\
828 <xsl:stylesheet version="1.0"
829 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
830 xmlns:myns="testns"
831 extension-element-prefixes="myns"
832 exclude-result-prefixes="myns">
833 <xsl:template match="a">
834 <A><myns:myext>b</myns:myext></A>
835 </xsl:template>
836 </xsl:stylesheet>''')
837
838 class MyError(Exception):
839 pass
840
841 class MyExt(etree.XSLTExtension):
842 def execute(self, context, self_node, input_node, output_parent):
843 raise MyError("expected!")
844
845 extensions = { ('testns', 'myext') : MyExt() }
846 self.assertRaises(MyError, tree.xslt, style, extensions=extensions)
847
849
850 xslt = etree.XSLT(etree.XML("""\
851 <xsl:stylesheet version="1.0"
852 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
853 <xsl:template match="/">
854 <test>TEXT<xsl:copy-of select="document('')//test"/></test>
855 </xsl:template>
856 </xsl:stylesheet>
857 """))
858 result = xslt(etree.XML('<a/>'))
859 root = result.getroot()
860 self.assertEquals(root.tag,
861 'test')
862 self.assertEquals(root[0].tag,
863 'test')
864 self.assertEquals(root[0].text,
865 'TEXT')
866 self.assertEquals(root[0][0].tag,
867 '{http://www.w3.org/1999/XSL/Transform}copy-of')
868
878
888
890 xslt = etree.XSLT(etree.XML("""\
891 <xsl:stylesheet version="1.0"
892 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
893 <xsl:template match="/">
894 <test>TEXT<xsl:copy-of select="document('uri:__junkfood__is__evil__')//test"/></test>
895 </xsl:template>
896 </xsl:stylesheet>
897 """))
898 self.assertRaises(etree.XSLTApplyError, xslt, etree.XML('<a/>'))
899
901
902 assertEquals = self.assertEquals
903 called = {'count' : 0}
904 class TestResolver(etree.Resolver):
905 def resolve(self, url, id, context):
906 assertEquals(url, 'file://ANYTHING')
907 called['count'] += 1
908 return self.resolve_string('<CALLED/>', context)
909
910 parser = etree.XMLParser()
911 parser.resolvers.add(TestResolver())
912
913 xslt = etree.XSLT(etree.XML(_bytes("""\
914 <xsl:stylesheet version="1.0"
915 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
916 xmlns:l="local">
917 <xsl:template match="/">
918 <test>
919 <xsl:for-each select="document('')//l:data/l:entry">
920 <xsl:copy-of select="document('file://ANYTHING')"/>
921 <xsl:copy>
922 <xsl:attribute name="value">
923 <xsl:value-of select="."/>
924 </xsl:attribute>
925 </xsl:copy>
926 </xsl:for-each>
927 </test>
928 </xsl:template>
929 <l:data>
930 <l:entry>A</l:entry>
931 <l:entry>B</l:entry>
932 </l:data>
933 </xsl:stylesheet>
934 """), parser))
935
936 self.assertEquals(called['count'], 0)
937 result = xslt(etree.XML('<a/>'))
938 self.assertEquals(called['count'], 1)
939
940 root = result.getroot()
941 self.assertEquals(root.tag,
942 'test')
943 self.assertEquals(len(root), 4)
944
945 self.assertEquals(root[0].tag,
946 'CALLED')
947 self.assertEquals(root[1].tag,
948 '{local}entry')
949 self.assertEquals(root[1].text,
950 None)
951 self.assertEquals(root[1].get("value"),
952 'A')
953 self.assertEquals(root[2].tag,
954 'CALLED')
955 self.assertEquals(root[3].tag,
956 '{local}entry')
957 self.assertEquals(root[3].text,
958 None)
959 self.assertEquals(root[3].get("value"),
960 'B')
961
963 assertEquals = self.assertEquals
964 called = {'count' : 0}
965 expected_url = None
966 class TestResolver(etree.Resolver):
967 def resolve(self, url, id, context):
968 assertEquals(url, expected_url)
969 called['count'] += 1
970 return self.resolve_string('<CALLED/>', context)
971
972 stylesheet_xml = _bytes("""\
973 <xsl:stylesheet version="1.0"
974 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
975 xmlns:l="local">
976 <xsl:template match="/">
977 <xsl:copy-of select="document('test.xml')"/>
978 </xsl:template>
979 </xsl:stylesheet>
980 """)
981
982 parser = etree.XMLParser()
983 parser.resolvers.add(TestResolver())
984
985
986 expected_url = 'test.xml'
987 xslt = etree.XSLT(etree.XML(stylesheet_xml, parser))
988
989 self.assertEquals(called['count'], 0)
990 result = xslt(etree.XML('<a/>'))
991 self.assertEquals(called['count'], 1)
992
993
994 called['count'] = 0
995 expected_url = os.path.join('MY', 'BASE', 'test.xml')
996 xslt = etree.XSLT(etree.XML(stylesheet_xml, parser,
997 base_url=os.path.join('MY', 'BASE', 'FILE')))
998
999 self.assertEquals(called['count'], 0)
1000 result = xslt(etree.XML('<a/>'))
1001 self.assertEquals(called['count'], 1)
1002
1003
1004 called['count'] = 0
1005 expected_url = 'http://server.com/BASE/DIR/test.xml'
1006 xslt = etree.XSLT(etree.XML(stylesheet_xml, parser,
1007 base_url='http://server.com/BASE/DIR/FILE'))
1008
1009 self.assertEquals(called['count'], 0)
1010 result = xslt(etree.XML('<a/>'))
1011 self.assertEquals(called['count'], 1)
1012
1023
1029
1035
1037 root = etree.XML(_bytes('''\
1038 <transform>
1039 <widget displayType="fieldset"/>
1040 </transform>'''))
1041
1042 xslt = etree.XSLT(etree.XML(_bytes('''\
1043 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1044 <xsl:output method="html" indent="no"/>
1045 <xsl:template match="/">
1046 <html>
1047 <xsl:apply-templates/>
1048 </html>
1049 </xsl:template>
1050
1051 <xsl:template match="widget">
1052 <xsl:element name="{@displayType}"/>
1053 </xsl:template>
1054
1055 </xsl:stylesheet>''')))
1056
1057 result = xslt(root[0])
1058 root[:] = result.getroot()[:]
1059 del root
1060
1062 tree = self.parse('''\
1063 <?xml version="1.0"?>
1064 <?xml-stylesheet type="text/xsl" href="%s"?>
1065 <a>
1066 <b>B</b>
1067 <c>C</c>
1068 </a>''' % fileInTestDir("test1.xslt"))
1069
1070 style_root = tree.getroot().getprevious().parseXSL().getroot()
1071 self.assertEquals("{http://www.w3.org/1999/XSL/Transform}stylesheet",
1072 style_root.tag)
1073
1075
1076 tree = self.parse('''\
1077 <?xml version="1.0"?>
1078 <?xml-stylesheet type="text/xsl" href="#style"?>
1079 <a>
1080 <b>B</b>
1081 <c>C</c>
1082 <xsl:stylesheet version="1.0" xml:id="style"
1083 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1084 <xsl:template match="*" />
1085 <xsl:template match="/">
1086 <foo><xsl:value-of select="/a/b/text()" /></foo>
1087 </xsl:template>
1088 </xsl:stylesheet>
1089 </a>''')
1090
1091 style_root = tree.getroot().getprevious().parseXSL().getroot()
1092 self.assertEquals("{http://www.w3.org/1999/XSL/Transform}stylesheet",
1093 style_root.tag)
1094
1095 st = etree.XSLT(style_root)
1096 res = st(tree)
1097 self.assertEquals('''\
1098 <?xml version="1.0"?>
1099 <foo>B</foo>
1100 ''',
1101 str(res))
1102
1104
1105 tree = self.parse('''\
1106 <?xml version="1.0"?>
1107 <?xml-stylesheet type="text/xsl" href="#style"?>
1108 <a>
1109 <b>B</b>
1110 <c>C</c>
1111 </a>''')
1112
1113 style = self.parse('''\
1114 <xsl:stylesheet version="1.0" xml:id="style"
1115 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1116 <xsl:template match="*" />
1117 <xsl:template match="/">
1118 <foo><xsl:value-of select="/a/b/text()" /></foo>
1119 </xsl:template>
1120 </xsl:stylesheet>
1121 ''')
1122
1123 tree.getroot().append(style.getroot())
1124
1125 style_root = tree.getroot().getprevious().parseXSL().getroot()
1126 self.assertEquals("{http://www.w3.org/1999/XSL/Transform}stylesheet",
1127 style_root.tag)
1128
1129 st = etree.XSLT(style_root)
1130 res = st(tree)
1131 self.assertEquals('''\
1132 <?xml version="1.0"?>
1133 <foo>B</foo>
1134 ''',
1135 str(res))
1136
1138 tree = self.parse('''\
1139 <?xml version="1.0"?>
1140 <?xml-stylesheet type="text/xsl" href="TEST"?>
1141 <a>
1142 <b>B</b>
1143 <c>C</c>
1144 </a>''')
1145
1146 pi = tree.getroot().getprevious()
1147 self.assertEquals("TEST", pi.get("href"))
1148
1150 tree = self.parse('''\
1151 <?xml version="1.0"?>
1152 <?xml-stylesheet type="text/xsl" href="TEST"?>
1153 <a>
1154 <b>B</b>
1155 <c>C</c>
1156 </a>''')
1157
1158 pi = tree.getroot().getprevious()
1159 self.assertEquals("TEST", pi.get("href"))
1160 self.assertEquals("text/xsl", pi.get("type"))
1161 self.assertEquals(None, pi.get("motz"))
1162
1164 tree = self.parse('''\
1165 <?xml version="1.0"?>
1166 <?xml-stylesheet href="TEST" type="text/xsl"?>
1167 <a>
1168 <b>B</b>
1169 <c>C</c>
1170 </a>''')
1171
1172 pi = tree.getroot().getprevious()
1173 self.assertEquals("TEST", pi.get("href"))
1174 self.assertEquals("text/xsl", pi.get("type"))
1175 self.assertEquals(None, pi.get("motz"))
1176
1178 tree = self.parse('''\
1179 <?xml version="1.0"?>
1180 <?xml-stylesheet type="text/xsl" href="TEST"?>
1181 <a>
1182 <b>B</b>
1183 <c>C</c>
1184 </a>''')
1185
1186 pi = tree.getroot().getprevious()
1187 self.assertEquals(None, pi.get("unknownattribute"))
1188
1190 tree = self.parse('''\
1191 <?xml version="1.0"?>
1192 <?xml-stylesheet type="text/xsl" href="TEST"?>
1193 <a>
1194 <b>B</b>
1195 <c>C</c>
1196 </a>''')
1197
1198 pi = tree.getroot().getprevious()
1199 self.assertEquals("TEST", pi.get("href"))
1200
1201 pi.set("href", "TEST123")
1202 self.assertEquals("TEST123", pi.get("href"))
1203
1205 tree = self.parse('''\
1206 <?xml version="1.0"?>
1207 <?xml-stylesheet type="text/xsl"?>
1208 <a>
1209 <b>B</b>
1210 <c>C</c>
1211 </a>''')
1212
1213 pi = tree.getroot().getprevious()
1214 self.assertEquals(None, pi.get("href"))
1215
1216 pi.set("href", "TEST")
1217 self.assertEquals("TEST", pi.get("href"))
1218
1220 xslt = etree.XSLT(etree.XML(_bytes("""\
1221 <xsl:stylesheet version="1.0"
1222 xmlns:regexp="http://exslt.org/regular-expressions"
1223 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1224 <xsl:template match="*">
1225 <test><xsl:copy-of select="*[regexp:test(string(.), '8.')]"/></test>
1226 </xsl:template>
1227 </xsl:stylesheet>
1228 """)))
1229 result = xslt(etree.XML(_bytes('<a><b>123</b><b>098</b><b>987</b></a>')))
1230 root = result.getroot()
1231 self.assertEquals(root.tag,
1232 'test')
1233 self.assertEquals(len(root), 1)
1234 self.assertEquals(root[0].tag,
1235 'b')
1236 self.assertEquals(root[0].text,
1237 '987')
1238
1240 xslt = etree.XSLT(etree.XML("""\
1241 <xsl:stylesheet version="1.0"
1242 xmlns:regexp="http://exslt.org/regular-expressions"
1243 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1244 <xsl:template match="*">
1245 <test>
1246 <xsl:copy-of select="regexp:replace(string(.), 'd.', '', 'XX')"/>
1247 <xsl:text>-</xsl:text>
1248 <xsl:copy-of select="regexp:replace(string(.), 'd.', 'gi', 'XX')"/>
1249 </test>
1250 </xsl:template>
1251 </xsl:stylesheet>
1252 """))
1253 result = xslt(etree.XML(_bytes('<a>abdCdEeDed</a>')))
1254 root = result.getroot()
1255 self.assertEquals(root.tag,
1256 'test')
1257 self.assertEquals(len(root), 0)
1258 self.assertEquals(root.text, 'abXXdEeDed-abXXXXeXXd')
1259
1261 xslt = etree.XSLT(etree.XML("""\
1262 <xsl:stylesheet version="1.0"
1263 xmlns:regexp="http://exslt.org/regular-expressions"
1264 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1265 <xsl:template match="*">
1266 <test>
1267 <test1><xsl:copy-of select="regexp:match(string(.), 'd.')"/></test1>
1268 <test2><xsl:copy-of select="regexp:match(string(.), 'd.', 'g')"/></test2>
1269 <test2i><xsl:copy-of select="regexp:match(string(.), 'd.', 'gi')"/></test2i>
1270 </test>
1271 </xsl:template>
1272 </xsl:stylesheet>
1273 """))
1274 result = xslt(etree.XML(_bytes('<a>abdCdEeDed</a>')))
1275 root = result.getroot()
1276 self.assertEquals(root.tag, 'test')
1277 self.assertEquals(len(root), 3)
1278
1279 self.assertEquals(len(root[0]), 1)
1280 self.assertEquals(root[0][0].tag, 'match')
1281 self.assertEquals(root[0][0].text, 'dC')
1282
1283 self.assertEquals(len(root[1]), 2)
1284 self.assertEquals(root[1][0].tag, 'match')
1285 self.assertEquals(root[1][0].text, 'dC')
1286 self.assertEquals(root[1][1].tag, 'match')
1287 self.assertEquals(root[1][1].text, 'dE')
1288
1289 self.assertEquals(len(root[2]), 3)
1290 self.assertEquals(root[2][0].tag, 'match')
1291 self.assertEquals(root[2][0].text, 'dC')
1292 self.assertEquals(root[2][1].tag, 'match')
1293 self.assertEquals(root[2][1].text, 'dE')
1294 self.assertEquals(root[2][2].tag, 'match')
1295 self.assertEquals(root[2][2].text, 'De')
1296
1298 xslt = etree.XSLT(etree.XML(_bytes("""\
1299 <xsl:stylesheet version="1.0"
1300 xmlns:regexp="http://exslt.org/regular-expressions"
1301 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1302 <xsl:template match="/">
1303 <test>
1304 <xsl:for-each select="regexp:match(
1305 '123abc567', '([0-9]+)([a-z]+)([0-9]+)' )">
1306 <test1><xsl:value-of select="."/></test1>
1307 </xsl:for-each>
1308 </test>
1309 </xsl:template>
1310 </xsl:stylesheet>
1311 """)))
1312 result = xslt(etree.XML(_bytes('<a/>')))
1313 root = result.getroot()
1314 self.assertEquals(root.tag, 'test')
1315 self.assertEquals(len(root), 4)
1316
1317 self.assertEquals(root[0].text, "123abc567")
1318 self.assertEquals(root[1].text, "123")
1319 self.assertEquals(root[2].text, "abc")
1320 self.assertEquals(root[3].text, "567")
1321
1323
1324 xslt = etree.XSLT(etree.XML(_bytes("""\
1325 <xsl:stylesheet version="1.0"
1326 xmlns:regexp="http://exslt.org/regular-expressions"
1327 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1328 <xsl:template match="/">
1329 <test>
1330 <xsl:for-each select="regexp:match(
1331 'http://www.bayes.co.uk/xml/index.xml?/xml/utils/rechecker.xml',
1332 '(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)')">
1333 <test1><xsl:value-of select="."/></test1>
1334 </xsl:for-each>
1335 </test>
1336 </xsl:template>
1337 </xsl:stylesheet>
1338 """)))
1339 result = xslt(etree.XML(_bytes('<a/>')))
1340 root = result.getroot()
1341 self.assertEquals(root.tag, 'test')
1342 self.assertEquals(len(root), 5)
1343
1344 self.assertEquals(
1345 root[0].text,
1346 "http://www.bayes.co.uk/xml/index.xml?/xml/utils/rechecker.xml")
1347 self.assertEquals(
1348 root[1].text,
1349 "http")
1350 self.assertEquals(
1351 root[2].text,
1352 "www.bayes.co.uk")
1353 self.assertFalse(root[3].text)
1354 self.assertEquals(
1355 root[4].text,
1356 "/xml/index.xml?/xml/utils/rechecker.xml")
1357
1359
1360 xslt = etree.XSLT(self.parse("""\
1361 <xsl:stylesheet version="1.0"
1362 xmlns:regexp="http://exslt.org/regular-expressions"
1363 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1364 <xsl:template match="/">
1365 <test>
1366 <xsl:for-each select="regexp:match(
1367 'This is a test string', '(\w+)', 'g')">
1368 <test1><xsl:value-of select="."/></test1>
1369 </xsl:for-each>
1370 </test>
1371 </xsl:template>
1372 </xsl:stylesheet>
1373 """))
1374 result = xslt(etree.XML(_bytes('<a/>')))
1375 root = result.getroot()
1376 self.assertEquals(root.tag, 'test')
1377 self.assertEquals(len(root), 5)
1378
1379 self.assertEquals(root[0].text, "This")
1380 self.assertEquals(root[1].text, "is")
1381 self.assertEquals(root[2].text, "a")
1382 self.assertEquals(root[3].text, "test")
1383 self.assertEquals(root[4].text, "string")
1384
1386
1387
1388 xslt = etree.XSLT(etree.XML(_bytes("""\
1389 <xsl:stylesheet version="1.0"
1390 xmlns:regexp="http://exslt.org/regular-expressions"
1391 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1392 <xsl:template match="/">
1393 <test>
1394 <xsl:for-each select="regexp:match(
1395 'This is a test string', '([a-z])+ ', 'g')">
1396 <test1><xsl:value-of select="."/></test1>
1397 </xsl:for-each>
1398 </test>
1399 </xsl:template>
1400 </xsl:stylesheet>
1401 """)))
1402 result = xslt(etree.XML(_bytes('<a/>')))
1403 root = result.getroot()
1404 self.assertEquals(root.tag, 'test')
1405 self.assertEquals(len(root), 4)
1406
1407 self.assertEquals(root[0].text, "his")
1408 self.assertEquals(root[1].text, "is")
1409 self.assertEquals(root[2].text, "a")
1410 self.assertEquals(root[3].text, "test")
1411
1413
1414
1415 xslt = etree.XSLT(etree.XML(_bytes("""\
1416 <xsl:stylesheet version="1.0"
1417 xmlns:regexp="http://exslt.org/regular-expressions"
1418 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1419 <xsl:template match="/">
1420 <test>
1421 <xsl:for-each select="regexp:match(
1422 'This is a test string', '([a-z])+ ', 'gi')">
1423 <test1><xsl:value-of select="."/></test1>
1424 </xsl:for-each>
1425 </test>
1426 </xsl:template>
1427 </xsl:stylesheet>
1428 """)))
1429 result = xslt(etree.XML(_bytes('<a/>')))
1430 root = result.getroot()
1431 self.assertEquals(root.tag, 'test')
1432 self.assertEquals(len(root), 4)
1433
1434 self.assertEquals(root[0].text, "This")
1435 self.assertEquals(root[1].text, "is")
1436 self.assertEquals(root[2].text, "a")
1437 self.assertEquals(root[3].text, "test")
1438
1439
1441 """XSLT tests for etree under Python 3"""
1443 tree = self.parse('<a><b>B</b><c>C</c></a>')
1444 style = self.parse('''\
1445 <xsl:stylesheet version="1.0"
1446 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1447 <xsl:template match="*" />
1448 <xsl:template match="/">
1449 <foo><xsl:value-of select="/a/b/text()" /></foo>
1450 </xsl:template>
1451 </xsl:stylesheet>''')
1452
1453 st = etree.XSLT(style)
1454 res = st(tree)
1455 self.assertEquals(_bytes('''\
1456 <?xml version="1.0"?>
1457 <foo>B</foo>
1458 '''),
1459 bytes(res))
1460
1462 tree = self.parse('<a><b>B</b><c>C</c></a>')
1463 style = self.parse('''\
1464 <xsl:stylesheet version="1.0"
1465 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1466 <xsl:template match="*" />
1467 <xsl:template match="/">
1468 <foo><xsl:value-of select="/a/b/text()" /></foo>
1469 </xsl:template>
1470 </xsl:stylesheet>''')
1471
1472 st = etree.XSLT(style)
1473 res = st(tree)
1474 self.assertEquals(_bytes('''\
1475 <?xml version="1.0"?>
1476 <foo>B</foo>
1477 '''),
1478 bytearray(res))
1479
1481 tree = self.parse('<a><b>B</b><c>C</c></a>')
1482 style = self.parse('''\
1483 <xsl:stylesheet version="1.0"
1484 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1485 <xsl:template match="*" />
1486 <xsl:template match="/">
1487 <foo><xsl:value-of select="/a/b/text()" /></foo>
1488 </xsl:template>
1489 </xsl:stylesheet>''')
1490
1491 st = etree.XSLT(style)
1492 res = st(tree)
1493 self.assertEquals(_bytes('''\
1494 <?xml version="1.0"?>
1495 <foo>B</foo>
1496 '''),
1497 bytes(memoryview(res)))
1498
1499
1501 suite = unittest.TestSuite()
1502 suite.addTests([unittest.makeSuite(ETreeXSLTTestCase)])
1503 if is_python3:
1504 suite.addTests([unittest.makeSuite(Py3XSLTTestCase)])
1505 suite.addTests(
1506 [make_doctest('../../../doc/extensions.txt')])
1507 suite.addTests(
1508 [make_doctest('../../../doc/xpathxslt.txt')])
1509 return suite
1510
1511 if __name__ == '__main__':
1512 print('to test use test.py %s' % __file__)
1513