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:param name="bar"/>
338 <xsl:template match="/">
339 <foo><xsl:value-of select="$bar" /></foo>
340 </xsl:template>
341 </xsl:stylesheet>''')
342
343 st = etree.XSLT(style)
344 res = self.assertRaises(etree.XSLTApplyError,
345 st, tree, bar="<test/>")
346 res = self.assertRaises(etree.XSLTApplyError,
347 st, tree, bar="....")
348
349 if etree.LIBXSLT_VERSION < (1,1,18):
350
352
353 tree = self.parse('<a><b>B</b><c>C</c></a>')
354 style = self.parse('''\
355 <xsl:stylesheet version="1.0"
356 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
357 <xsl:template match="/">
358 <foo><xsl:value-of select="$bar" /></foo>
359 </xsl:template>
360 </xsl:stylesheet>''')
361
362 st = etree.XSLT(style)
363 self.assertRaises(etree.XSLTApplyError,
364 st.apply, tree)
365
367 tree = self.parse('<a><b>B</b><c>C</c></a>')
368 style = self.parse('''\
369 <xsl:stylesheet version="1.0"
370 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
371 <xsl:template match="*" />
372 <xsl:template match="/">
373 <foo><xsl:value-of select="$bar" /></foo>
374 <foo><xsl:value-of select="$baz" /></foo>
375 </xsl:template>
376 </xsl:stylesheet>''')
377
378 st = etree.XSLT(style)
379 res = st(tree, bar="'Bar'", baz="'Baz'")
380 self.assertEquals('''\
381 <?xml version="1.0"?>
382 <foo>Bar</foo><foo>Baz</foo>
383 ''',
384 str(res))
385
387 tree = self.parse('<a><b>B</b><c>C</c></a>')
388 style = self.parse('''\
389 <xsl:stylesheet version="1.0"
390 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
391 <xsl:template match="*" />
392 <xsl:template match="/">
393 <foo><xsl:value-of select="$bar" /></foo>
394 </xsl:template>
395 </xsl:stylesheet>''')
396
397 st = etree.XSLT(style)
398 res = st(tree, bar="/a/b/text()")
399 self.assertEquals('''\
400 <?xml version="1.0"?>
401 <foo>B</foo>
402 ''',
403 str(res))
404
405
407 tree = self.parse('<a><b>B</b><c>C</c></a>')
408 style = self.parse('''\
409 <xsl:stylesheet version="1.0"
410 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
411 <xsl:param name="bar" select="'Default'" />
412 <xsl:template match="*" />
413 <xsl:template match="/">
414 <foo><xsl:value-of select="$bar" /></foo>
415 </xsl:template>
416 </xsl:stylesheet>''')
417
418 st = etree.XSLT(style)
419 res = st(tree, bar="'Bar'")
420 self.assertEquals('''\
421 <?xml version="1.0"?>
422 <foo>Bar</foo>
423 ''',
424 str(res))
425 res = st(tree)
426 self.assertEquals('''\
427 <?xml version="1.0"?>
428 <foo>Default</foo>
429 ''',
430 str(res))
431
433 tree = self.parse('<a><b>B</b><c>C</c></a>')
434 style = self.parse('''\
435 <xsl:stylesheet version="1.0"
436 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
437 <xsl:output method="html"/>
438 <xsl:strip-space elements="*"/>
439 <xsl:template match="/">
440 <html><body><xsl:value-of select="/a/b/text()" /></body></html>
441 </xsl:template>
442 </xsl:stylesheet>''')
443
444 st = etree.XSLT(style)
445 res = st(tree)
446 self.assertEquals('<html><body>B</body></html>',
447 str(res).strip())
448
452
458
481
506
508
509 xml = '<blah/>'
510 xslt = '''
511 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
512 <xsl:template match="/" />
513 </xsl:stylesheet>
514 '''
515
516 source = self.parse(xml)
517 styledoc = self.parse(xslt)
518 style = etree.XSLT(styledoc)
519 result = style(source)
520 self.assertEqual('', str(result))
521
523 xml = '<blah/>'
524 xslt = '''
525 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
526 <xsl:template match="/">
527 <xsl:message>TEST TEST TEST</xsl:message>
528 </xsl:template>
529 </xsl:stylesheet>
530 '''
531
532 source = self.parse(xml)
533 styledoc = self.parse(xslt)
534 style = etree.XSLT(styledoc)
535 result = style(source)
536 self.assertEqual('', str(result))
537 self.assert_("TEST TEST TEST" in [entry.message
538 for entry in style.error_log])
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 terminate="yes">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
554 self.assertRaises(etree.XSLTApplyError, style, source)
555 self.assert_("TEST TEST TEST" in [entry.message
556 for entry in style.error_log])
557
559 tree = self.parse('<a><b>B</b><c>C</c></a>')
560 style = self.parse('''\
561 <xsl:stylesheet version="1.0"
562 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
563 <xsl:template match="*" />
564 <xsl:template match="/">
565 <doc>
566 <foo><xsl:value-of select="$bar" /></foo>
567 <foo><xsl:value-of select="$baz" /></foo>
568 </doc>
569 </xsl:template>
570 </xsl:stylesheet>''')
571
572 result = tree.xslt(style, bar="'Bar'", baz="'Baz'")
573 self.assertEquals(
574 _bytes('<doc><foo>Bar</foo><foo>Baz</foo></doc>'),
575 etree.tostring(result.getroot()))
576
578 tree = self.parse('<a><b>B</b><c>C</c></a>')
579 style = self.parse('''\
580 <xsl:stylesheet version="1.0"
581 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
582 <xsl:template match="a"><A><xsl:apply-templates/></A></xsl:template>
583 <xsl:template match="b"><B><xsl:apply-templates/></B></xsl:template>
584 <xsl:template match="c"><C><xsl:apply-templates/></C></xsl:template>
585 </xsl:stylesheet>''')
586
587 self.assertEquals(self._rootstring(tree),
588 _bytes('<a><b>B</b><c>C</c></a>'))
589 result = tree.xslt(style)
590 self.assertEquals(self._rootstring(tree),
591 _bytes('<a><b>B</b><c>C</c></a>'))
592 self.assertEquals(self._rootstring(result),
593 _bytes('<A><B>B</B><C>C</C></A>'))
594
595 b_tree = etree.ElementTree(tree.getroot()[0])
596 self.assertEquals(self._rootstring(b_tree),
597 _bytes('<b>B</b>'))
598 result = b_tree.xslt(style)
599 self.assertEquals(self._rootstring(tree),
600 _bytes('<a><b>B</b><c>C</c></a>'))
601 self.assertEquals(self._rootstring(result),
602 _bytes('<B>B</B>'))
603
604 c_tree = etree.ElementTree(tree.getroot()[1])
605 self.assertEquals(self._rootstring(c_tree),
606 _bytes('<c>C</c>'))
607 result = c_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('<C>C</C>'))
612
614 tree = self.parse('<a><b>B</b></a>')
615 style = self.parse('''\
616 <xsl:stylesheet version="1.0"
617 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
618 xmlns:myns="testns"
619 exclude-result-prefixes="myns">
620 <xsl:template match="a"><A><xsl:value-of select="myns:mytext(b)"/></A></xsl:template>
621 </xsl:stylesheet>''')
622
623 def mytext(ctxt, values):
624 return 'X' * len(values)
625
626 result = tree.xslt(style, {('testns', 'mytext') : mytext})
627 self.assertEquals(self._rootstring(result),
628 _bytes('<A>X</A>'))
629
631 tree = self.parse('<a><b>B</b></a>')
632 style = self.parse('''\
633 <xsl:stylesheet version="1.0"
634 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
635 xmlns:myns="testns"
636 exclude-result-prefixes="myns">
637 <xsl:template match="a"><A><xsl:value-of select="myns:mytext(b)"/></A></xsl:template>
638 </xsl:stylesheet>''')
639
640 def mytext(ctxt, values):
641 return 'X' * len(values)
642
643 namespace = etree.FunctionNamespace('testns')
644 namespace['mytext'] = mytext
645
646 result = tree.xslt(style)
647 self.assertEquals(self._rootstring(result),
648 _bytes('<A>X</A>'))
649
651 tree = self.parse('<a><b>B</b></a>')
652 style = self.parse('''\
653 <xsl:stylesheet version="1.0"
654 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
655 xmlns:myns="testns"
656 extension-element-prefixes="myns"
657 exclude-result-prefixes="myns">
658 <xsl:template match="a">
659 <A><myns:myext>b</myns:myext></A>
660 </xsl:template>
661 </xsl:stylesheet>''')
662
663 class MyExt(etree.XSLTExtension):
664 def execute(self, context, self_node, input_node, output_parent):
665 child = etree.Element(self_node.text)
666 child.text = 'X'
667 output_parent.append(child)
668
669 extensions = { ('testns', 'myext') : MyExt() }
670
671 result = tree.xslt(style, extensions=extensions)
672 self.assertEquals(self._rootstring(result),
673 _bytes('<A><b>X</b></A>'))
674
676 tree = self.parse('<a><b>B</b></a>')
677 style = self.parse('''\
678 <xsl:stylesheet version="1.0"
679 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
680 xmlns:myns="testns"
681 extension-element-prefixes="myns">
682 <xsl:template match="a">
683 <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
684 </xsl:template>
685 </xsl:stylesheet>''')
686
687 class MyExt(etree.XSLTExtension):
688 def execute(self, context, self_node, input_node, output_parent):
689 output_parent.extend(list(self_node)[1:])
690
691 extensions = { ('testns', 'myext') : MyExt() }
692
693 result = tree.xslt(style, extensions=extensions)
694 self.assertEquals(self._rootstring(result),
695 _bytes('<A><y>Y</y><z/></A>'))
696
698 tree = self.parse('<a><b>B</b></a>')
699 style = self.parse('''\
700 <xsl:stylesheet version="1.0"
701 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
702 xmlns:myns="testns"
703 extension-element-prefixes="myns">
704 <xsl:template match="a">
705 <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
706 </xsl:template>
707 <xsl:template match="x" />
708 <xsl:template match="z">XYZ</xsl:template>
709 </xsl:stylesheet>''')
710
711 class MyExt(etree.XSLTExtension):
712 def execute(self, context, self_node, input_node, output_parent):
713 for child in self_node:
714 for result in self.apply_templates(context, child):
715 if isinstance(result, basestring):
716 el = etree.Element("T")
717 el.text = result
718 else:
719 el = result
720 output_parent.append(el)
721
722 extensions = { ('testns', 'myext') : MyExt() }
723
724 result = tree.xslt(style, extensions=extensions)
725 self.assertEquals(self._rootstring(result),
726 _bytes('<A><T>Y</T><T>XYZ</T></A>'))
727
729 tree = self.parse('<a><b>B</b></a>')
730 style = self.parse('''\
731 <xsl:stylesheet version="1.0"
732 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
733 xmlns:myns="testns"
734 extension-element-prefixes="myns"
735 exclude-result-prefixes="myns">
736 <xsl:template match="a">
737 <A><myns:myext>b</myns:myext></A>
738 </xsl:template>
739 </xsl:stylesheet>''')
740
741 class MyError(Exception):
742 pass
743
744 class MyExt(etree.XSLTExtension):
745 def execute(self, context, self_node, input_node, output_parent):
746 raise MyError("expected!")
747
748 extensions = { ('testns', 'myext') : MyExt() }
749 self.assertRaises(MyError, tree.xslt, style, extensions=extensions)
750
752
753 xslt = etree.XSLT(etree.XML("""\
754 <xsl:stylesheet version="1.0"
755 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
756 <xsl:template match="/">
757 <test>TEXT<xsl:copy-of select="document('')//test"/></test>
758 </xsl:template>
759 </xsl:stylesheet>
760 """))
761 result = xslt(etree.XML('<a/>'))
762 root = result.getroot()
763 self.assertEquals(root.tag,
764 'test')
765 self.assertEquals(root[0].tag,
766 'test')
767 self.assertEquals(root[0].text,
768 'TEXT')
769 self.assertEquals(root[0][0].tag,
770 '{http://www.w3.org/1999/XSL/Transform}copy-of')
771
781
791
793 xslt = etree.XSLT(etree.XML("""\
794 <xsl:stylesheet version="1.0"
795 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
796 <xsl:template match="/">
797 <test>TEXT<xsl:copy-of select="document('uri:__junkfood__is__evil__')//test"/></test>
798 </xsl:template>
799 </xsl:stylesheet>
800 """))
801 self.assertRaises(etree.XSLTApplyError, xslt, etree.XML('<a/>'))
802
804
805 assertEquals = self.assertEquals
806 called = {'count' : 0}
807 class TestResolver(etree.Resolver):
808 def resolve(self, url, id, context):
809 assertEquals(url, 'file://ANYTHING')
810 called['count'] += 1
811 return self.resolve_string('<CALLED/>', context)
812
813 parser = etree.XMLParser()
814 parser.resolvers.add(TestResolver())
815
816 xslt = etree.XSLT(etree.XML(_bytes("""\
817 <xsl:stylesheet version="1.0"
818 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
819 xmlns:l="local">
820 <xsl:template match="/">
821 <test>
822 <xsl:for-each select="document('')//l:data/l:entry">
823 <xsl:copy-of select="document('file://ANYTHING')"/>
824 <xsl:copy>
825 <xsl:attribute name="value">
826 <xsl:value-of select="."/>
827 </xsl:attribute>
828 </xsl:copy>
829 </xsl:for-each>
830 </test>
831 </xsl:template>
832 <l:data>
833 <l:entry>A</l:entry>
834 <l:entry>B</l:entry>
835 </l:data>
836 </xsl:stylesheet>
837 """), parser))
838
839 self.assertEquals(called['count'], 0)
840 result = xslt(etree.XML('<a/>'))
841 self.assertEquals(called['count'], 1)
842
843 root = result.getroot()
844 self.assertEquals(root.tag,
845 'test')
846 self.assertEquals(len(root), 4)
847
848 self.assertEquals(root[0].tag,
849 'CALLED')
850 self.assertEquals(root[1].tag,
851 '{local}entry')
852 self.assertEquals(root[1].text,
853 None)
854 self.assertEquals(root[1].get("value"),
855 'A')
856 self.assertEquals(root[2].tag,
857 'CALLED')
858 self.assertEquals(root[3].tag,
859 '{local}entry')
860 self.assertEquals(root[3].text,
861 None)
862 self.assertEquals(root[3].get("value"),
863 'B')
864
875
881
887
889 root = etree.XML(_bytes('''\
890 <transform>
891 <widget displayType="fieldset"/>
892 </transform>'''))
893
894 xslt = etree.XSLT(etree.XML(_bytes('''\
895 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
896 <xsl:output method="html" indent="no"/>
897 <xsl:template match="/">
898 <html>
899 <xsl:apply-templates/>
900 </html>
901 </xsl:template>
902
903 <xsl:template match="widget">
904 <xsl:element name="{@displayType}"/>
905 </xsl:template>
906
907 </xsl:stylesheet>''')))
908
909 result = xslt(root[0])
910 root[:] = result.getroot()[:]
911 del root
912
914 tree = self.parse('''\
915 <?xml version="1.0"?>
916 <?xml-stylesheet type="text/xsl" href="%s"?>
917 <a>
918 <b>B</b>
919 <c>C</c>
920 </a>''' % fileInTestDir("test1.xslt"))
921
922 style_root = tree.getroot().getprevious().parseXSL().getroot()
923 self.assertEquals("{http://www.w3.org/1999/XSL/Transform}stylesheet",
924 style_root.tag)
925
927
928 tree = self.parse('''\
929 <?xml version="1.0"?>
930 <?xml-stylesheet type="text/xsl" href="#style"?>
931 <a>
932 <b>B</b>
933 <c>C</c>
934 <xsl:stylesheet version="1.0" xml:id="style"
935 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
936 <xsl:template match="*" />
937 <xsl:template match="/">
938 <foo><xsl:value-of select="/a/b/text()" /></foo>
939 </xsl:template>
940 </xsl:stylesheet>
941 </a>''')
942
943 style_root = tree.getroot().getprevious().parseXSL().getroot()
944 self.assertEquals("{http://www.w3.org/1999/XSL/Transform}stylesheet",
945 style_root.tag)
946
947 st = etree.XSLT(style_root)
948 res = st(tree)
949 self.assertEquals('''\
950 <?xml version="1.0"?>
951 <foo>B</foo>
952 ''',
953 str(res))
954
956
957 tree = self.parse('''\
958 <?xml version="1.0"?>
959 <?xml-stylesheet type="text/xsl" href="#style"?>
960 <a>
961 <b>B</b>
962 <c>C</c>
963 </a>''')
964
965 style = self.parse('''\
966 <xsl:stylesheet version="1.0" xml:id="style"
967 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
968 <xsl:template match="*" />
969 <xsl:template match="/">
970 <foo><xsl:value-of select="/a/b/text()" /></foo>
971 </xsl:template>
972 </xsl:stylesheet>
973 ''')
974
975 tree.getroot().append(style.getroot())
976
977 style_root = tree.getroot().getprevious().parseXSL().getroot()
978 self.assertEquals("{http://www.w3.org/1999/XSL/Transform}stylesheet",
979 style_root.tag)
980
981 st = etree.XSLT(style_root)
982 res = st(tree)
983 self.assertEquals('''\
984 <?xml version="1.0"?>
985 <foo>B</foo>
986 ''',
987 str(res))
988
990 tree = self.parse('''\
991 <?xml version="1.0"?>
992 <?xml-stylesheet type="text/xsl" href="TEST"?>
993 <a>
994 <b>B</b>
995 <c>C</c>
996 </a>''')
997
998 pi = tree.getroot().getprevious()
999 self.assertEquals("TEST", pi.get("href"))
1000
1002 tree = self.parse('''\
1003 <?xml version="1.0"?>
1004 <?xml-stylesheet type="text/xsl" href="TEST"?>
1005 <a>
1006 <b>B</b>
1007 <c>C</c>
1008 </a>''')
1009
1010 pi = tree.getroot().getprevious()
1011 self.assertEquals("TEST", pi.get("href"))
1012 self.assertEquals("text/xsl", pi.get("type"))
1013 self.assertEquals(None, pi.get("motz"))
1014
1016 tree = self.parse('''\
1017 <?xml version="1.0"?>
1018 <?xml-stylesheet href="TEST" type="text/xsl"?>
1019 <a>
1020 <b>B</b>
1021 <c>C</c>
1022 </a>''')
1023
1024 pi = tree.getroot().getprevious()
1025 self.assertEquals("TEST", pi.get("href"))
1026 self.assertEquals("text/xsl", pi.get("type"))
1027 self.assertEquals(None, pi.get("motz"))
1028
1030 tree = self.parse('''\
1031 <?xml version="1.0"?>
1032 <?xml-stylesheet type="text/xsl" href="TEST"?>
1033 <a>
1034 <b>B</b>
1035 <c>C</c>
1036 </a>''')
1037
1038 pi = tree.getroot().getprevious()
1039 self.assertEquals(None, pi.get("unknownattribute"))
1040
1042 tree = self.parse('''\
1043 <?xml version="1.0"?>
1044 <?xml-stylesheet type="text/xsl" href="TEST"?>
1045 <a>
1046 <b>B</b>
1047 <c>C</c>
1048 </a>''')
1049
1050 pi = tree.getroot().getprevious()
1051 self.assertEquals("TEST", pi.get("href"))
1052
1053 pi.set("href", "TEST123")
1054 self.assertEquals("TEST123", pi.get("href"))
1055
1057 tree = self.parse('''\
1058 <?xml version="1.0"?>
1059 <?xml-stylesheet type="text/xsl"?>
1060 <a>
1061 <b>B</b>
1062 <c>C</c>
1063 </a>''')
1064
1065 pi = tree.getroot().getprevious()
1066 self.assertEquals(None, pi.get("href"))
1067
1068 pi.set("href", "TEST")
1069 self.assertEquals("TEST", pi.get("href"))
1070
1072 xslt = etree.XSLT(etree.XML(_bytes("""\
1073 <xsl:stylesheet version="1.0"
1074 xmlns:regexp="http://exslt.org/regular-expressions"
1075 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1076 <xsl:template match="*">
1077 <test><xsl:copy-of select="*[regexp:test(string(.), '8.')]"/></test>
1078 </xsl:template>
1079 </xsl:stylesheet>
1080 """)))
1081 result = xslt(etree.XML(_bytes('<a><b>123</b><b>098</b><b>987</b></a>')))
1082 root = result.getroot()
1083 self.assertEquals(root.tag,
1084 'test')
1085 self.assertEquals(len(root), 1)
1086 self.assertEquals(root[0].tag,
1087 'b')
1088 self.assertEquals(root[0].text,
1089 '987')
1090
1092 xslt = etree.XSLT(etree.XML("""\
1093 <xsl:stylesheet version="1.0"
1094 xmlns:regexp="http://exslt.org/regular-expressions"
1095 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1096 <xsl:template match="*">
1097 <test>
1098 <xsl:copy-of select="regexp:replace(string(.), 'd.', '', 'XX')"/>
1099 <xsl:text>-</xsl:text>
1100 <xsl:copy-of select="regexp:replace(string(.), 'd.', 'gi', 'XX')"/>
1101 </test>
1102 </xsl:template>
1103 </xsl:stylesheet>
1104 """))
1105 result = xslt(etree.XML(_bytes('<a>abdCdEeDed</a>')))
1106 root = result.getroot()
1107 self.assertEquals(root.tag,
1108 'test')
1109 self.assertEquals(len(root), 0)
1110 self.assertEquals(root.text, 'abXXdEeDed-abXXXXeXXd')
1111
1113 xslt = etree.XSLT(etree.XML("""\
1114 <xsl:stylesheet version="1.0"
1115 xmlns:regexp="http://exslt.org/regular-expressions"
1116 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1117 <xsl:template match="*">
1118 <test>
1119 <test1><xsl:copy-of select="regexp:match(string(.), 'd.')"/></test1>
1120 <test2><xsl:copy-of select="regexp:match(string(.), 'd.', 'g')"/></test2>
1121 <test2i><xsl:copy-of select="regexp:match(string(.), 'd.', 'gi')"/></test2i>
1122 </test>
1123 </xsl:template>
1124 </xsl:stylesheet>
1125 """))
1126 result = xslt(etree.XML(_bytes('<a>abdCdEeDed</a>')))
1127 root = result.getroot()
1128 self.assertEquals(root.tag, 'test')
1129 self.assertEquals(len(root), 3)
1130
1131 self.assertEquals(len(root[0]), 1)
1132 self.assertEquals(root[0][0].tag, 'match')
1133 self.assertEquals(root[0][0].text, 'dC')
1134
1135 self.assertEquals(len(root[1]), 2)
1136 self.assertEquals(root[1][0].tag, 'match')
1137 self.assertEquals(root[1][0].text, 'dC')
1138 self.assertEquals(root[1][1].tag, 'match')
1139 self.assertEquals(root[1][1].text, 'dE')
1140
1141 self.assertEquals(len(root[2]), 3)
1142 self.assertEquals(root[2][0].tag, 'match')
1143 self.assertEquals(root[2][0].text, 'dC')
1144 self.assertEquals(root[2][1].tag, 'match')
1145 self.assertEquals(root[2][1].text, 'dE')
1146 self.assertEquals(root[2][2].tag, 'match')
1147 self.assertEquals(root[2][2].text, 'De')
1148
1150 xslt = etree.XSLT(etree.XML(_bytes("""\
1151 <xsl:stylesheet version="1.0"
1152 xmlns:regexp="http://exslt.org/regular-expressions"
1153 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1154 <xsl:template match="/">
1155 <test>
1156 <xsl:for-each select="regexp:match(
1157 '123abc567', '([0-9]+)([a-z]+)([0-9]+)' )">
1158 <test1><xsl:value-of select="."/></test1>
1159 </xsl:for-each>
1160 </test>
1161 </xsl:template>
1162 </xsl:stylesheet>
1163 """)))
1164 result = xslt(etree.XML(_bytes('<a/>')))
1165 root = result.getroot()
1166 self.assertEquals(root.tag, 'test')
1167 self.assertEquals(len(root), 4)
1168
1169 self.assertEquals(root[0].text, "123abc567")
1170 self.assertEquals(root[1].text, "123")
1171 self.assertEquals(root[2].text, "abc")
1172 self.assertEquals(root[3].text, "567")
1173
1175
1176 xslt = etree.XSLT(etree.XML(_bytes("""\
1177 <xsl:stylesheet version="1.0"
1178 xmlns:regexp="http://exslt.org/regular-expressions"
1179 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1180 <xsl:template match="/">
1181 <test>
1182 <xsl:for-each select="regexp:match(
1183 'http://www.bayes.co.uk/xml/index.xml?/xml/utils/rechecker.xml',
1184 '(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)')">
1185 <test1><xsl:value-of select="."/></test1>
1186 </xsl:for-each>
1187 </test>
1188 </xsl:template>
1189 </xsl:stylesheet>
1190 """)))
1191 result = xslt(etree.XML(_bytes('<a/>')))
1192 root = result.getroot()
1193 self.assertEquals(root.tag, 'test')
1194 self.assertEquals(len(root), 5)
1195
1196 self.assertEquals(
1197 root[0].text,
1198 "http://www.bayes.co.uk/xml/index.xml?/xml/utils/rechecker.xml")
1199 self.assertEquals(
1200 root[1].text,
1201 "http")
1202 self.assertEquals(
1203 root[2].text,
1204 "www.bayes.co.uk")
1205 self.assertFalse(root[3].text)
1206 self.assertEquals(
1207 root[4].text,
1208 "/xml/index.xml?/xml/utils/rechecker.xml")
1209
1211
1212 xslt = etree.XSLT(self.parse("""\
1213 <xsl:stylesheet version="1.0"
1214 xmlns:regexp="http://exslt.org/regular-expressions"
1215 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1216 <xsl:template match="/">
1217 <test>
1218 <xsl:for-each select="regexp:match(
1219 'This is a test string', '(\w+)', 'g')">
1220 <test1><xsl:value-of select="."/></test1>
1221 </xsl:for-each>
1222 </test>
1223 </xsl:template>
1224 </xsl:stylesheet>
1225 """))
1226 result = xslt(etree.XML(_bytes('<a/>')))
1227 root = result.getroot()
1228 self.assertEquals(root.tag, 'test')
1229 self.assertEquals(len(root), 5)
1230
1231 self.assertEquals(root[0].text, "This")
1232 self.assertEquals(root[1].text, "is")
1233 self.assertEquals(root[2].text, "a")
1234 self.assertEquals(root[3].text, "test")
1235 self.assertEquals(root[4].text, "string")
1236
1238
1239
1240 xslt = etree.XSLT(etree.XML(_bytes("""\
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:for-each select="regexp:match(
1247 'This is a test string', '([a-z])+ ', 'g')">
1248 <test1><xsl:value-of select="."/></test1>
1249 </xsl:for-each>
1250 </test>
1251 </xsl:template>
1252 </xsl:stylesheet>
1253 """)))
1254 result = xslt(etree.XML(_bytes('<a/>')))
1255 root = result.getroot()
1256 self.assertEquals(root.tag, 'test')
1257 self.assertEquals(len(root), 4)
1258
1259 self.assertEquals(root[0].text, "his")
1260 self.assertEquals(root[1].text, "is")
1261 self.assertEquals(root[2].text, "a")
1262 self.assertEquals(root[3].text, "test")
1263
1265
1266
1267 xslt = etree.XSLT(etree.XML(_bytes("""\
1268 <xsl:stylesheet version="1.0"
1269 xmlns:regexp="http://exslt.org/regular-expressions"
1270 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1271 <xsl:template match="/">
1272 <test>
1273 <xsl:for-each select="regexp:match(
1274 'This is a test string', '([a-z])+ ', 'gi')">
1275 <test1><xsl:value-of select="."/></test1>
1276 </xsl:for-each>
1277 </test>
1278 </xsl:template>
1279 </xsl:stylesheet>
1280 """)))
1281 result = xslt(etree.XML(_bytes('<a/>')))
1282 root = result.getroot()
1283 self.assertEquals(root.tag, 'test')
1284 self.assertEquals(len(root), 4)
1285
1286 self.assertEquals(root[0].text, "This")
1287 self.assertEquals(root[1].text, "is")
1288 self.assertEquals(root[2].text, "a")
1289 self.assertEquals(root[3].text, "test")
1290
1291
1293 """XSLT tests for etree under Python 3"""
1295 tree = self.parse('<a><b>B</b><c>C</c></a>')
1296 style = self.parse('''\
1297 <xsl:stylesheet version="1.0"
1298 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1299 <xsl:template match="*" />
1300 <xsl:template match="/">
1301 <foo><xsl:value-of select="/a/b/text()" /></foo>
1302 </xsl:template>
1303 </xsl:stylesheet>''')
1304
1305 st = etree.XSLT(style)
1306 res = st(tree)
1307 self.assertEquals(_bytes('''\
1308 <?xml version="1.0"?>
1309 <foo>B</foo>
1310 '''),
1311 bytes(res))
1312
1314 tree = self.parse('<a><b>B</b><c>C</c></a>')
1315 style = self.parse('''\
1316 <xsl:stylesheet version="1.0"
1317 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1318 <xsl:template match="*" />
1319 <xsl:template match="/">
1320 <foo><xsl:value-of select="/a/b/text()" /></foo>
1321 </xsl:template>
1322 </xsl:stylesheet>''')
1323
1324 st = etree.XSLT(style)
1325 res = st(tree)
1326 self.assertEquals(_bytes('''\
1327 <?xml version="1.0"?>
1328 <foo>B</foo>
1329 '''),
1330 bytearray(res))
1331
1333 tree = self.parse('<a><b>B</b><c>C</c></a>')
1334 style = self.parse('''\
1335 <xsl:stylesheet version="1.0"
1336 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1337 <xsl:template match="*" />
1338 <xsl:template match="/">
1339 <foo><xsl:value-of select="/a/b/text()" /></foo>
1340 </xsl:template>
1341 </xsl:stylesheet>''')
1342
1343 st = etree.XSLT(style)
1344 res = st(tree)
1345 self.assertEquals(_bytes('''\
1346 <?xml version="1.0"?>
1347 <foo>B</foo>
1348 '''),
1349 bytes(memoryview(res)))
1350
1351
1353 suite = unittest.TestSuite()
1354 suite.addTests([unittest.makeSuite(ETreeXSLTTestCase)])
1355 if is_python3:
1356 suite.addTests([unittest.makeSuite(Py3XSLTTestCase)])
1357 suite.addTests(
1358 [make_doctest('../../../doc/extensions.txt')])
1359 suite.addTests(
1360 [make_doctest('../../../doc/xpathxslt.txt')])
1361 return suite
1362
1363 if __name__ == '__main__':
1364 print('to test use test.py %s' % __file__)
1365