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
17 except NameError:
18 unicode = str
19
20 try:
21 basestring
22 except NameError:
23 basestring = str
24
25 from common_imports import etree, BytesIO, HelperTestCase, fileInTestDir
26 from common_imports import doctest, _bytes, _str, make_doctest, skipif
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.assertEqual('''\
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.assertEqual('''\
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.assertEqual('''\
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.assertEqual('''\
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.assertEqual(expected,
124 str(bytes(res), 'UTF-8'))
125 else:
126 self.assertEqual(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.assertEqual(expected,
149 str(bytes(res), 'UTF-16'))
150 else:
151 self.assertEqual(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.assertEqual(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.assertEqual(expected,
199 unicode(res))
200
202 tree = self.parse(_bytes('<a><b>\\uF8D2</b><c>\\uF8D2</c></a>'
203 ).decode("unicode_escape"))
204 style = self.parse('''\
205 <xsl:stylesheet version="1.0"
206 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
207 <xsl:output encoding="UTF-16" standalone="no"/>
208 <xsl:template match="/">
209 <foo><xsl:value-of select="/a/b/text()" /></foo>
210 </xsl:template>
211 </xsl:stylesheet>''')
212
213 st = etree.XSLT(style)
214 res = st(tree)
215 expected = _bytes('''\
216 <?xml version="1.0" standalone="no"?>
217 <foo>\\uF8D2</foo>
218 ''').decode("unicode_escape")
219 self.assertEqual(expected,
220 unicode(res))
221
234
251
253 tree = self.parse('<a/>')
254 style = self.parse('''\
255 <xsl:stylesheet version="1.0"
256 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
257 <xsl:foo />
258 </xsl:stylesheet>''')
259 self.assertRaises(etree.XSLTParseError,
260 etree.XSLT, style)
261
263 tree = self.parse('<a><b>B</b><c>C</c></a>')
264 style = self.parse('''\
265 <xsl:stylesheet version="1.0"
266 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
267 <xsl:template match="/">
268 <foo><xsl:value-of select="$bar" /></foo>
269 </xsl:template>
270 </xsl:stylesheet>''')
271
272 st = etree.XSLT(style)
273 res = st(tree, bar="'Bar'")
274 self.assertEqual('''\
275 <?xml version="1.0"?>
276 <foo>Bar</foo>
277 ''',
278 str(res))
279
281 tree = self.parse('<a><b>B</b><c>C</c></a>')
282 style = self.parse('''\
283 <xsl:stylesheet version="1.0"
284 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
285 <xsl:template match="/">
286 <foo><xsl:value-of select="$bar" /></foo>
287 </xsl:template>
288 </xsl:stylesheet>''')
289
290 st = etree.XSLT(style)
291 res = st(tree, bar=etree.XSLT.strparam('''it's me, "Bar"'''))
292 self.assertEqual('''\
293 <?xml version="1.0"?>
294 <foo>it's me, "Bar"</foo>
295 ''',
296 str(res))
297
299 tree = self.parse('<a><b>B</b><c>C</c></a>')
300 style = self.parse('''\
301 <xsl:stylesheet version="1.0"
302 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
303 <xsl:param name="bar"/>
304 <xsl:template match="/">
305 <foo><xsl:value-of select="$bar" /></foo>
306 </xsl:template>
307 </xsl:stylesheet>''')
308
309 st = etree.XSLT(style)
310 res = self.assertRaises(etree.XSLTApplyError,
311 st, tree, bar="<test/>")
312 res = self.assertRaises(etree.XSLTApplyError,
313 st, tree, bar="....")
314
315 if etree.LIBXSLT_VERSION < (1,1,18):
316
318
319 tree = self.parse('<a><b>B</b><c>C</c></a>')
320 style = self.parse('''\
321 <xsl:stylesheet version="1.0"
322 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
323 <xsl:template match="/">
324 <foo><xsl:value-of select="$bar" /></foo>
325 </xsl:template>
326 </xsl:stylesheet>''')
327
328 st = etree.XSLT(style)
329 self.assertRaises(etree.XSLTApplyError,
330 st.apply, tree)
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 <xsl:template match="/">
339 <foo><xsl:value-of select="$bar" /></foo>
340 <foo><xsl:value-of select="$baz" /></foo>
341 </xsl:template>
342 </xsl:stylesheet>''')
343
344 st = etree.XSLT(style)
345 res = st(tree, bar="'Bar'", baz="'Baz'")
346 self.assertEqual('''\
347 <?xml version="1.0"?>
348 <foo>Bar</foo><foo>Baz</foo>
349 ''',
350 str(res))
351
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 <xsl:template match="/">
359 <foo><xsl:value-of select="$bar" /></foo>
360 </xsl:template>
361 </xsl:stylesheet>''')
362
363 st = etree.XSLT(style)
364 res = st(tree, bar="/a/b/text()")
365 self.assertEqual('''\
366 <?xml version="1.0"?>
367 <foo>B</foo>
368 ''',
369 str(res))
370
372 tree = self.parse('<a><b>B</b><c>C</c></a>')
373 style = self.parse('''\
374 <xsl:stylesheet version="1.0"
375 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
376 <xsl:template match="*" />
377 <xsl:template match="/">
378 <foo><xsl:value-of select="$bar" /></foo>
379 </xsl:template>
380 </xsl:stylesheet>''')
381
382 st = etree.XSLT(style)
383 res = st(tree, bar=etree.XPath("/a/b/text()"))
384 self.assertEqual('''\
385 <?xml version="1.0"?>
386 <foo>B</foo>
387 ''',
388 str(res))
389
391 tree = self.parse('<a><b>B</b><c>C</c></a>')
392 style = self.parse('''\
393 <xsl:stylesheet version="1.0"
394 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
395 <xsl:param name="bar" select="'Default'" />
396 <xsl:template match="*" />
397 <xsl:template match="/">
398 <foo><xsl:value-of select="$bar" /></foo>
399 </xsl:template>
400 </xsl:stylesheet>''')
401
402 st = etree.XSLT(style)
403 res = st(tree, bar="'Bar'")
404 self.assertEqual('''\
405 <?xml version="1.0"?>
406 <foo>Bar</foo>
407 ''',
408 str(res))
409 res = st(tree)
410 self.assertEqual('''\
411 <?xml version="1.0"?>
412 <foo>Default</foo>
413 ''',
414 str(res))
415
417 tree = self.parse('<a><b>B</b><c>C</c></a>')
418 style = self.parse('''\
419 <xsl:stylesheet version="1.0"
420 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
421 <xsl:output method="html"/>
422 <xsl:strip-space elements="*"/>
423 <xsl:template match="/">
424 <html><body><xsl:value-of select="/a/b/text()" /></body></html>
425 </xsl:template>
426 </xsl:stylesheet>''')
427
428 st = etree.XSLT(style)
429 res = st(tree)
430 self.assertEqual('<html><body>B</body></html>',
431 str(res).strip())
432
436
442
465
490
492
493 xml = '<blah/>'
494 xslt = '''
495 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
496 <xsl:template match="/" />
497 </xsl:stylesheet>
498 '''
499
500 source = self.parse(xml)
501 styledoc = self.parse(xslt)
502 style = etree.XSLT(styledoc)
503 result = style(source)
504 self.assertEqual('', str(result))
505
507 xml = '<blah/>'
508 xslt = '''
509 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
510 <xsl:template match="/">
511 <xsl:message>TEST TEST TEST</xsl:message>
512 </xsl:template>
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 self.assertTrue("TEST TEST TEST" in [entry.message
522 for entry in style.error_log])
523
525 xml = '<blah/>'
526 xslt = '''
527 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
528 <xsl:template match="/">
529 <xsl:message terminate="yes">TEST TEST TEST</xsl:message>
530 </xsl:template>
531 </xsl:stylesheet>
532 '''
533
534 source = self.parse(xml)
535 styledoc = self.parse(xslt)
536 style = etree.XSLT(styledoc)
537
538 self.assertRaises(etree.XSLTApplyError, style, source)
539 self.assertTrue("TEST TEST TEST" in [entry.message
540 for entry in style.error_log])
541
543 tree = self.parse('<a><b>B</b><c>C</c></a>')
544 style = self.parse('''\
545 <xsl:stylesheet version="1.0"
546 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
547 <xsl:template match="*" />
548 <xsl:template match="/">
549 <doc>
550 <foo><xsl:value-of select="$bar" /></foo>
551 <foo><xsl:value-of select="$baz" /></foo>
552 </doc>
553 </xsl:template>
554 </xsl:stylesheet>''')
555
556 result = tree.xslt(style, bar="'Bar'", baz="'Baz'")
557 self.assertEqual(
558 _bytes('<doc><foo>Bar</foo><foo>Baz</foo></doc>'),
559 etree.tostring(result.getroot()))
560
562 tree = self.parse('<a><b>B</b><c>C</c></a>')
563 style = self.parse('''\
564 <xsl:stylesheet version="1.0"
565 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
566 <xsl:template match="a"><A><xsl:apply-templates/></A></xsl:template>
567 <xsl:template match="b"><B><xsl:apply-templates/></B></xsl:template>
568 <xsl:template match="c"><C><xsl:apply-templates/></C></xsl:template>
569 </xsl:stylesheet>''')
570
571 self.assertEqual(self._rootstring(tree),
572 _bytes('<a><b>B</b><c>C</c></a>'))
573 result = tree.xslt(style)
574 self.assertEqual(self._rootstring(tree),
575 _bytes('<a><b>B</b><c>C</c></a>'))
576 self.assertEqual(self._rootstring(result),
577 _bytes('<A><B>B</B><C>C</C></A>'))
578
579 b_tree = etree.ElementTree(tree.getroot()[0])
580 self.assertEqual(self._rootstring(b_tree),
581 _bytes('<b>B</b>'))
582 result = b_tree.xslt(style)
583 self.assertEqual(self._rootstring(tree),
584 _bytes('<a><b>B</b><c>C</c></a>'))
585 self.assertEqual(self._rootstring(result),
586 _bytes('<B>B</B>'))
587
588 c_tree = etree.ElementTree(tree.getroot()[1])
589 self.assertEqual(self._rootstring(c_tree),
590 _bytes('<c>C</c>'))
591 result = c_tree.xslt(style)
592 self.assertEqual(self._rootstring(tree),
593 _bytes('<a><b>B</b><c>C</c></a>'))
594 self.assertEqual(self._rootstring(result),
595 _bytes('<C>C</C>'))
596
598
599 xslt = etree.XSLT(etree.XML("""\
600 <xsl:stylesheet version="1.0"
601 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
602 <xsl:template match="/">
603 <test>TEXT<xsl:copy-of select="document('')//test"/></test>
604 </xsl:template>
605 </xsl:stylesheet>
606 """))
607 result = xslt(etree.XML('<a/>'))
608 root = result.getroot()
609 self.assertEqual(root.tag,
610 'test')
611 self.assertEqual(root[0].tag,
612 'test')
613 self.assertEqual(root[0].text,
614 'TEXT')
615 self.assertEqual(root[0][0].tag,
616 '{http://www.w3.org/1999/XSL/Transform}copy-of')
617
627
637
639 xslt = etree.XSLT(etree.XML("""\
640 <xsl:stylesheet version="1.0"
641 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
642 <xsl:template match="/">
643 <test>TEXT<xsl:copy-of select="document('uri:__junkfood__is__evil__')//test"/></test>
644 </xsl:template>
645 </xsl:stylesheet>
646 """))
647 self.assertRaises(etree.XSLTApplyError, xslt, etree.XML('<a/>'))
648
650
651 assertEqual = self.assertEqual
652 called = {'count' : 0}
653 class TestResolver(etree.Resolver):
654 def resolve(self, url, id, context):
655 assertEqual(url, 'file://ANYTHING')
656 called['count'] += 1
657 return self.resolve_string('<CALLED/>', context)
658
659 parser = etree.XMLParser()
660 parser.resolvers.add(TestResolver())
661
662 xslt = etree.XSLT(etree.XML(_bytes("""\
663 <xsl:stylesheet version="1.0"
664 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
665 xmlns:l="local">
666 <xsl:template match="/">
667 <test>
668 <xsl:for-each select="document('')//l:data/l:entry">
669 <xsl:copy-of select="document('file://ANYTHING')"/>
670 <xsl:copy>
671 <xsl:attribute name="value">
672 <xsl:value-of select="."/>
673 </xsl:attribute>
674 </xsl:copy>
675 </xsl:for-each>
676 </test>
677 </xsl:template>
678 <l:data>
679 <l:entry>A</l:entry>
680 <l:entry>B</l:entry>
681 </l:data>
682 </xsl:stylesheet>
683 """), parser))
684
685 self.assertEqual(called['count'], 0)
686 result = xslt(etree.XML('<a/>'))
687 self.assertEqual(called['count'], 1)
688
689 root = result.getroot()
690 self.assertEqual(root.tag,
691 'test')
692 self.assertEqual(len(root), 4)
693
694 self.assertEqual(root[0].tag,
695 'CALLED')
696 self.assertEqual(root[1].tag,
697 '{local}entry')
698 self.assertEqual(root[1].text,
699 None)
700 self.assertEqual(root[1].get("value"),
701 'A')
702 self.assertEqual(root[2].tag,
703 'CALLED')
704 self.assertEqual(root[3].tag,
705 '{local}entry')
706 self.assertEqual(root[3].text,
707 None)
708 self.assertEqual(root[3].get("value"),
709 'B')
710
712 assertEqual = self.assertEqual
713 called = {'count' : 0}
714 expected_url = None
715 class TestResolver(etree.Resolver):
716 def resolve(self, url, id, context):
717 assertEqual(url, expected_url)
718 called['count'] += 1
719 return self.resolve_string('<CALLED/>', context)
720
721 stylesheet_xml = _bytes("""\
722 <xsl:stylesheet version="1.0"
723 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
724 xmlns:l="local">
725 <xsl:template match="/">
726 <xsl:copy-of select="document('test.xml')"/>
727 </xsl:template>
728 </xsl:stylesheet>
729 """)
730
731 parser = etree.XMLParser()
732 parser.resolvers.add(TestResolver())
733
734
735 expected_url = 'test.xml'
736 xslt = etree.XSLT(etree.XML(stylesheet_xml, parser))
737
738 self.assertEqual(called['count'], 0)
739 result = xslt(etree.XML('<a/>'))
740 self.assertEqual(called['count'], 1)
741
742
743 called['count'] = 0
744 expected_url = os.path.join('MY', 'BASE', 'test.xml')
745 xslt = etree.XSLT(etree.XML(stylesheet_xml, parser,
746 base_url=os.path.join('MY', 'BASE', 'FILE')))
747
748 self.assertEqual(called['count'], 0)
749 result = xslt(etree.XML('<a/>'))
750 self.assertEqual(called['count'], 1)
751
752
753 called['count'] = 0
754 expected_url = 'http://server.com/BASE/DIR/test.xml'
755 xslt = etree.XSLT(etree.XML(stylesheet_xml, parser,
756 base_url='http://server.com/BASE/DIR/FILE'))
757
758 self.assertEqual(called['count'], 0)
759 result = xslt(etree.XML('<a/>'))
760 self.assertEqual(called['count'], 1)
761
772
778
784
786 root = etree.XML(_bytes('''\
787 <transform>
788 <widget displayType="fieldset"/>
789 </transform>'''))
790
791 xslt = etree.XSLT(etree.XML(_bytes('''\
792 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
793 <xsl:output method="html" indent="no"/>
794 <xsl:template match="/">
795 <html>
796 <xsl:apply-templates/>
797 </html>
798 </xsl:template>
799
800 <xsl:template match="widget">
801 <xsl:element name="{@displayType}"/>
802 </xsl:template>
803
804 </xsl:stylesheet>''')))
805
806 result = xslt(root[0])
807 root[:] = result.getroot()[:]
808 del root
809
811 tree = self.parse('''\
812 <?xml version="1.0"?>
813 <?xml-stylesheet type="text/xsl" href="%s"?>
814 <a>
815 <b>B</b>
816 <c>C</c>
817 </a>''' % fileInTestDir("test1.xslt"))
818
819 style_root = tree.getroot().getprevious().parseXSL().getroot()
820 self.assertEqual("{http://www.w3.org/1999/XSL/Transform}stylesheet",
821 style_root.tag)
822
824
825 tree = self.parse('''\
826 <?xml version="1.0"?>
827 <?xml-stylesheet type="text/xsl" href="#style"?>
828 <a>
829 <b>B</b>
830 <c>C</c>
831 <xsl:stylesheet version="1.0" xml:id="style"
832 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
833 <xsl:template match="*" />
834 <xsl:template match="/">
835 <foo><xsl:value-of select="/a/b/text()" /></foo>
836 </xsl:template>
837 </xsl:stylesheet>
838 </a>''')
839
840 style_root = tree.getroot().getprevious().parseXSL().getroot()
841 self.assertEqual("{http://www.w3.org/1999/XSL/Transform}stylesheet",
842 style_root.tag)
843
844 st = etree.XSLT(style_root)
845 res = st(tree)
846 self.assertEqual('''\
847 <?xml version="1.0"?>
848 <foo>B</foo>
849 ''',
850 str(res))
851
853
854 tree = self.parse('''\
855 <?xml version="1.0"?>
856 <?xml-stylesheet type="text/xsl" href="#style"?>
857 <a>
858 <b>B</b>
859 <c>C</c>
860 </a>''')
861
862 style = self.parse('''\
863 <xsl:stylesheet version="1.0" xml:id="style"
864 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
865 <xsl:template match="*" />
866 <xsl:template match="/">
867 <foo><xsl:value-of select="/a/b/text()" /></foo>
868 </xsl:template>
869 </xsl:stylesheet>
870 ''')
871
872 tree.getroot().append(style.getroot())
873
874 style_root = tree.getroot().getprevious().parseXSL().getroot()
875 self.assertEqual("{http://www.w3.org/1999/XSL/Transform}stylesheet",
876 style_root.tag)
877
878 st = etree.XSLT(style_root)
879 res = st(tree)
880 self.assertEqual('''\
881 <?xml version="1.0"?>
882 <foo>B</foo>
883 ''',
884 str(res))
885
887 tree = self.parse('''\
888 <?xml version="1.0"?>
889 <?xml-stylesheet type="text/xsl" href="TEST"?>
890 <a>
891 <b>B</b>
892 <c>C</c>
893 </a>''')
894
895 pi = tree.getroot().getprevious()
896 self.assertEqual("TEST", pi.get("href"))
897
899 tree = self.parse('''\
900 <?xml version="1.0"?>
901 <?xml-stylesheet type="text/xsl" href="TEST"?>
902 <a>
903 <b>B</b>
904 <c>C</c>
905 </a>''')
906
907 pi = tree.getroot().getprevious()
908 self.assertEqual("TEST", pi.get("href"))
909 self.assertEqual("text/xsl", pi.get("type"))
910 self.assertEqual(None, pi.get("motz"))
911
913 tree = self.parse('''\
914 <?xml version="1.0"?>
915 <?xml-stylesheet href="TEST" type="text/xsl"?>
916 <a>
917 <b>B</b>
918 <c>C</c>
919 </a>''')
920
921 pi = tree.getroot().getprevious()
922 self.assertEqual("TEST", pi.get("href"))
923 self.assertEqual("text/xsl", pi.get("type"))
924 self.assertEqual(None, pi.get("motz"))
925
927 tree = self.parse('''\
928 <?xml version="1.0"?>
929 <?xml-stylesheet type="text/xsl" href="TEST"?>
930 <a>
931 <b>B</b>
932 <c>C</c>
933 </a>''')
934
935 pi = tree.getroot().getprevious()
936 self.assertEqual(None, pi.get("unknownattribute"))
937
939 tree = self.parse('''\
940 <?xml version="1.0"?>
941 <?xml-stylesheet type="text/xsl" href="TEST"?>
942 <a>
943 <b>B</b>
944 <c>C</c>
945 </a>''')
946
947 pi = tree.getroot().getprevious()
948 self.assertEqual("TEST", pi.get("href"))
949
950 pi.set("href", "TEST123")
951 self.assertEqual("TEST123", pi.get("href"))
952
954 tree = self.parse('''\
955 <?xml version="1.0"?>
956 <?xml-stylesheet type="text/xsl"?>
957 <a>
958 <b>B</b>
959 <c>C</c>
960 </a>''')
961
962 pi = tree.getroot().getprevious()
963 self.assertEqual(None, pi.get("href"))
964
965 pi.set("href", "TEST")
966 self.assertEqual("TEST", pi.get("href"))
967
969 """EXSLT tests"""
970
972 tree = self.parse('<a><b>B</b><c>C</c></a>')
973 style = self.parse('''\
974 <xsl:stylesheet version="1.0"
975 xmlns:str="http://exslt.org/strings"
976 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
977 exclude-result-prefixes="str xsl">
978 <xsl:template match="text()">
979 <xsl:value-of select="str:align(string(.), '***', 'center')" />
980 </xsl:template>
981 <xsl:template match="*">
982 <xsl:copy>
983 <xsl:apply-templates/>
984 </xsl:copy>
985 </xsl:template>
986 </xsl:stylesheet>''')
987
988 st = etree.XSLT(style)
989 res = st(tree)
990 self.assertEqual('''\
991 <?xml version="1.0"?>
992 <a><b>*B*</b><c>*C*</c></a>
993 ''',
994 str(res))
995
996 if etree.LIBXSLT_VERSION >= (1,1,21):
998 tree = self.parse('<a><b>B</b><c>C</c></a>')
999 style = self.parse('''\
1000 <xsl:stylesheet version = "1.0"
1001 xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
1002 xmlns:str="http://exslt.org/strings"
1003 extension-element-prefixes="str">
1004
1005 <xsl:template match="/">
1006 <h1 class="{str:replace('abc', 'b', 'x')}">test</h1>
1007 </xsl:template>
1008
1009 </xsl:stylesheet>''')
1010
1011 st = etree.XSLT(style)
1012 res = st(tree)
1013 self.assertEqual('''\
1014 <?xml version="1.0"?>
1015 <h1 class="axc">test</h1>
1016 ''',
1017 str(res))
1018
1020 tree = self.parse('<a><b>B</b><c>C</c></a>')
1021 style = self.parse('''\
1022 <xsl:stylesheet version="1.0"
1023 xmlns:math="http://exslt.org/math"
1024 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1025 exclude-result-prefixes="math xsl">
1026 <xsl:template match="*">
1027 <xsl:copy>
1028 <xsl:attribute name="pi">
1029 <xsl:value-of select="math:constant('PI', count(*)+2)"/>
1030 </xsl:attribute>
1031 <xsl:apply-templates/>
1032 </xsl:copy>
1033 </xsl:template>
1034 </xsl:stylesheet>''')
1035
1036 st = etree.XSLT(style)
1037 res = st(tree)
1038 self.assertEqual('''\
1039 <?xml version="1.0"?>
1040 <a pi="3.14"><b pi="3">B</b><c pi="3">C</c></a>
1041 ''',
1042 str(res))
1043
1045 xslt = etree.XSLT(etree.XML(_bytes("""\
1046 <xsl:stylesheet version="1.0"
1047 xmlns:regexp="http://exslt.org/regular-expressions"
1048 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1049 <xsl:template match="*">
1050 <test><xsl:copy-of select="*[regexp:test(string(.), '8.')]"/></test>
1051 </xsl:template>
1052 </xsl:stylesheet>
1053 """)))
1054 result = xslt(etree.XML(_bytes('<a><b>123</b><b>098</b><b>987</b></a>')))
1055 root = result.getroot()
1056 self.assertEqual(root.tag,
1057 'test')
1058 self.assertEqual(len(root), 1)
1059 self.assertEqual(root[0].tag,
1060 'b')
1061 self.assertEqual(root[0].text,
1062 '987')
1063
1065 xslt = etree.XSLT(etree.XML("""\
1066 <xsl:stylesheet version="1.0"
1067 xmlns:regexp="http://exslt.org/regular-expressions"
1068 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1069 <xsl:template match="*">
1070 <test>
1071 <xsl:copy-of select="regexp:replace(string(.), 'd.', '', 'XX')"/>
1072 <xsl:text>-</xsl:text>
1073 <xsl:copy-of select="regexp:replace(string(.), 'd.', 'gi', 'XX')"/>
1074 </test>
1075 </xsl:template>
1076 </xsl:stylesheet>
1077 """))
1078 result = xslt(etree.XML(_bytes('<a>abdCdEeDed</a>')))
1079 root = result.getroot()
1080 self.assertEqual(root.tag,
1081 'test')
1082 self.assertEqual(len(root), 0)
1083 self.assertEqual(root.text, 'abXXdEeDed-abXXXXeXXd')
1084
1086 xslt = etree.XSLT(etree.XML("""\
1087 <xsl:stylesheet version="1.0"
1088 xmlns:regexp="http://exslt.org/regular-expressions"
1089 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1090 <xsl:template match="*">
1091 <test>
1092 <test1><xsl:copy-of select="regexp:match(string(.), 'd.')"/></test1>
1093 <test2><xsl:copy-of select="regexp:match(string(.), 'd.', 'g')"/></test2>
1094 <test2i><xsl:copy-of select="regexp:match(string(.), 'd.', 'gi')"/></test2i>
1095 </test>
1096 </xsl:template>
1097 </xsl:stylesheet>
1098 """))
1099 result = xslt(etree.XML(_bytes('<a>abdCdEeDed</a>')))
1100 root = result.getroot()
1101 self.assertEqual(root.tag, 'test')
1102 self.assertEqual(len(root), 3)
1103
1104 self.assertEqual(len(root[0]), 1)
1105 self.assertEqual(root[0][0].tag, 'match')
1106 self.assertEqual(root[0][0].text, 'dC')
1107
1108 self.assertEqual(len(root[1]), 2)
1109 self.assertEqual(root[1][0].tag, 'match')
1110 self.assertEqual(root[1][0].text, 'dC')
1111 self.assertEqual(root[1][1].tag, 'match')
1112 self.assertEqual(root[1][1].text, 'dE')
1113
1114 self.assertEqual(len(root[2]), 3)
1115 self.assertEqual(root[2][0].tag, 'match')
1116 self.assertEqual(root[2][0].text, 'dC')
1117 self.assertEqual(root[2][1].tag, 'match')
1118 self.assertEqual(root[2][1].text, 'dE')
1119 self.assertEqual(root[2][2].tag, 'match')
1120 self.assertEqual(root[2][2].text, 'De')
1121
1123 xslt = etree.XSLT(etree.XML(_bytes("""\
1124 <xsl:stylesheet version="1.0"
1125 xmlns:regexp="http://exslt.org/regular-expressions"
1126 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1127 <xsl:template match="/">
1128 <test>
1129 <xsl:for-each select="regexp:match(
1130 '123abc567', '([0-9]+)([a-z]+)([0-9]+)' )">
1131 <test1><xsl:value-of select="."/></test1>
1132 </xsl:for-each>
1133 </test>
1134 </xsl:template>
1135 </xsl:stylesheet>
1136 """)))
1137 result = xslt(etree.XML(_bytes('<a/>')))
1138 root = result.getroot()
1139 self.assertEqual(root.tag, 'test')
1140 self.assertEqual(len(root), 4)
1141
1142 self.assertEqual(root[0].text, "123abc567")
1143 self.assertEqual(root[1].text, "123")
1144 self.assertEqual(root[2].text, "abc")
1145 self.assertEqual(root[3].text, "567")
1146
1148
1149 xslt = etree.XSLT(etree.XML(_bytes("""\
1150 <xsl:stylesheet version="1.0"
1151 xmlns:regexp="http://exslt.org/regular-expressions"
1152 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1153 <xsl:template match="/">
1154 <test>
1155 <xsl:for-each select="regexp:match(
1156 'http://www.bayes.co.uk/xml/index.xml?/xml/utils/rechecker.xml',
1157 '(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)')">
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.assertEqual(root.tag, 'test')
1167 self.assertEqual(len(root), 5)
1168
1169 self.assertEqual(
1170 root[0].text,
1171 "http://www.bayes.co.uk/xml/index.xml?/xml/utils/rechecker.xml")
1172 self.assertEqual(
1173 root[1].text,
1174 "http")
1175 self.assertEqual(
1176 root[2].text,
1177 "www.bayes.co.uk")
1178 self.assertFalse(root[3].text)
1179 self.assertEqual(
1180 root[4].text,
1181 "/xml/index.xml?/xml/utils/rechecker.xml")
1182
1184
1185 xslt = etree.XSLT(self.parse("""\
1186 <xsl:stylesheet version="1.0"
1187 xmlns:regexp="http://exslt.org/regular-expressions"
1188 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1189 <xsl:template match="/">
1190 <test>
1191 <xsl:for-each select="regexp:match(
1192 'This is a test string', '(\w+)', 'g')">
1193 <test1><xsl:value-of select="."/></test1>
1194 </xsl:for-each>
1195 </test>
1196 </xsl:template>
1197 </xsl:stylesheet>
1198 """))
1199 result = xslt(etree.XML(_bytes('<a/>')))
1200 root = result.getroot()
1201 self.assertEqual(root.tag, 'test')
1202 self.assertEqual(len(root), 5)
1203
1204 self.assertEqual(root[0].text, "This")
1205 self.assertEqual(root[1].text, "is")
1206 self.assertEqual(root[2].text, "a")
1207 self.assertEqual(root[3].text, "test")
1208 self.assertEqual(root[4].text, "string")
1209
1211
1212
1213 xslt = etree.XSLT(etree.XML(_bytes("""\
1214 <xsl:stylesheet version="1.0"
1215 xmlns:regexp="http://exslt.org/regular-expressions"
1216 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1217 <xsl:template match="/">
1218 <test>
1219 <xsl:for-each select="regexp:match(
1220 'This is a test string', '([a-z])+ ', 'g')">
1221 <test1><xsl:value-of select="."/></test1>
1222 </xsl:for-each>
1223 </test>
1224 </xsl:template>
1225 </xsl:stylesheet>
1226 """)))
1227 result = xslt(etree.XML(_bytes('<a/>')))
1228 root = result.getroot()
1229 self.assertEqual(root.tag, 'test')
1230 self.assertEqual(len(root), 4)
1231
1232 self.assertEqual(root[0].text, "his")
1233 self.assertEqual(root[1].text, "is")
1234 self.assertEqual(root[2].text, "a")
1235 self.assertEqual(root[3].text, "test")
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])+ ', 'gi')">
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.assertEqual(root.tag, 'test')
1257 self.assertEqual(len(root), 4)
1258
1259 self.assertEqual(root[0].text, "This")
1260 self.assertEqual(root[1].text, "is")
1261 self.assertEqual(root[2].text, "a")
1262 self.assertEqual(root[3].text, "test")
1263
1264
1265 -class ETreeXSLTExtFuncTestCase(HelperTestCase):
1266 """Tests for XPath extension functions in XSLT."""
1267
1268 - def test_extensions1(self):
1269 tree = self.parse('<a><b>B</b></a>')
1270 style = self.parse('''\
1271 <xsl:stylesheet version="1.0"
1272 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1273 xmlns:myns="testns"
1274 exclude-result-prefixes="myns">
1275 <xsl:template match="a"><A><xsl:value-of select="myns:mytext(b)"/></A></xsl:template>
1276 </xsl:stylesheet>''')
1277
1278 def mytext(ctxt, values):
1279 return 'X' * len(values)
1280
1281 result = tree.xslt(style, {('testns', 'mytext') : mytext})
1282 self.assertEqual(self._rootstring(result),
1283 _bytes('<A>X</A>'))
1284
1285 - def test_extensions2(self):
1286 tree = self.parse('<a><b>B</b></a>')
1287 style = self.parse('''\
1288 <xsl:stylesheet version="1.0"
1289 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1290 xmlns:myns="testns"
1291 exclude-result-prefixes="myns">
1292 <xsl:template match="a"><A><xsl:value-of select="myns:mytext(b)"/></A></xsl:template>
1293 </xsl:stylesheet>''')
1294
1295 def mytext(ctxt, values):
1296 return 'X' * len(values)
1297
1298 namespace = etree.FunctionNamespace('testns')
1299 namespace['mytext'] = mytext
1300
1301 result = tree.xslt(style)
1302 self.assertEqual(self._rootstring(result),
1303 _bytes('<A>X</A>'))
1304
1306 tree = self.parse('<a><b>B</b><b/></a>')
1307 style = self.parse('''\
1308 <xsl:stylesheet version="1.0"
1309 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1310 xmlns:myns="testns"
1311 exclude-result-prefixes="myns">
1312 <xsl:template match="a">
1313 <xsl:variable name="content">
1314 <xsl:apply-templates/>
1315 </xsl:variable>
1316 <A><xsl:value-of select="myns:mytext($content)"/></A>
1317 </xsl:template>
1318 <xsl:template match="b"><xsl:copy>BBB</xsl:copy></xsl:template>
1319 </xsl:stylesheet>''')
1320
1321 def mytext(ctxt, values):
1322 for value in values:
1323 self.assertTrue(hasattr(value, 'tag'),
1324 "%s is not an Element" % type(value))
1325 self.assertEqual(value.tag, 'b')
1326 self.assertEqual(value.text, 'BBB')
1327 return 'X'.join([el.tag for el in values])
1328
1329 namespace = etree.FunctionNamespace('testns')
1330 namespace['mytext'] = mytext
1331
1332 result = tree.xslt(style)
1333 self.assertEqual(self._rootstring(result),
1334 _bytes('<A>bXb</A>'))
1335
1336
1337 -class ETreeXSLTExtElementTestCase(HelperTestCase):
1338 """Tests for extension elements in XSLT."""
1339
1341 tree = self.parse('<a><b>B</b></a>')
1342 style = self.parse('''\
1343 <xsl:stylesheet version="1.0"
1344 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1345 xmlns:myns="testns"
1346 extension-element-prefixes="myns"
1347 exclude-result-prefixes="myns">
1348 <xsl:template match="a">
1349 <A><myns:myext>b</myns:myext></A>
1350 </xsl:template>
1351 </xsl:stylesheet>''')
1352
1353 class MyExt(etree.XSLTExtension):
1354 def execute(self, context, self_node, input_node, output_parent):
1355 child = etree.Element(self_node.text)
1356 child.text = 'X'
1357 output_parent.append(child)
1358
1359 extensions = { ('testns', 'myext') : MyExt() }
1360
1361 result = tree.xslt(style, extensions=extensions)
1362 self.assertEqual(self._rootstring(result),
1363 _bytes('<A><b>X</b></A>'))
1364
1366 tree = self.parse('<a><b>B</b></a>')
1367 style = self.parse('''\
1368 <xsl:stylesheet version="1.0"
1369 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1370 xmlns:myns="testns"
1371 extension-element-prefixes="myns"
1372 exclude-result-prefixes="myns">
1373 <xsl:template match="/">
1374 <A><myns:myext>b</myns:myext></A>
1375 </xsl:template>
1376 </xsl:stylesheet>''')
1377
1378 tags = []
1379
1380 class MyExt(etree.XSLTExtension):
1381 def execute(self, context, self_node, input_node, output_parent):
1382 tags.append(input_node.tag)
1383
1384 extensions = { ('testns', 'myext') : MyExt() }
1385
1386 result = tree.xslt(style, extensions=extensions)
1387 self.assertEqual(tags, ['a'])
1388
1390 tree = self.parse('<?test toast?><a><!--a comment--><?another pi?></a>')
1391 style = self.parse('''\
1392 <xsl:stylesheet version="1.0"
1393 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1394 xmlns:myns="testns"
1395 extension-element-prefixes="myns"
1396 exclude-result-prefixes="myns">
1397 <xsl:template match="/">
1398 <ROOT><xsl:apply-templates /></ROOT>
1399 </xsl:template>
1400 <xsl:template match="comment()">
1401 <A><myns:myext>b</myns:myext></A>
1402 </xsl:template>
1403 <xsl:template match="processing-instruction()">
1404 <A><myns:myext>b</myns:myext></A>
1405 </xsl:template>
1406 </xsl:stylesheet>''')
1407
1408 text = []
1409
1410 class MyExt(etree.XSLTExtension):
1411 def execute(self, context, self_node, input_node, output_parent):
1412 text.append(input_node.text)
1413
1414 extensions = { ('testns', 'myext') : MyExt() }
1415
1416 result = tree.xslt(style, extensions=extensions)
1417 self.assertEqual(text, ['toast', 'a comment', 'pi'])
1418
1420
1421 tree = self.parse('<a test="A"><b attr="B"/></a>')
1422 style = self.parse('''\
1423 <xsl:stylesheet version="1.0"
1424 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1425 xmlns:myns="testns"
1426 extension-element-prefixes="myns"
1427 exclude-result-prefixes="myns">
1428 <xsl:template match="@test">
1429 <A><myns:myext>b</myns:myext></A>
1430 </xsl:template>
1431 <xsl:template match="@attr">
1432 <A><myns:myext>b</myns:myext></A>
1433 </xsl:template>
1434 </xsl:stylesheet>''')
1435
1436 text = []
1437
1438 class MyExt(etree.XSLTExtension):
1439 def execute(self, context, self_node, attr_value, output_parent):
1440 text.append(attr_value)
1441
1442 extensions = { ('testns', 'myext') : MyExt() }
1443
1444 result = tree.xslt(style, extensions=extensions)
1445 self.assertEqual(text, ['A', 'B'])
1446
1448 tree = self.parse('<a><b>B</b></a>')
1449 style = self.parse('''\
1450 <xsl:stylesheet version="1.0"
1451 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1452 xmlns:myns="testns"
1453 extension-element-prefixes="myns">
1454 <xsl:template match="a">
1455 <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
1456 </xsl:template>
1457 </xsl:stylesheet>''')
1458
1459 class MyExt(etree.XSLTExtension):
1460 def execute(self, context, self_node, input_node, output_parent):
1461 output_parent.extend(list(self_node)[1:])
1462
1463 extensions = { ('testns', 'myext') : MyExt() }
1464
1465 result = tree.xslt(style, extensions=extensions)
1466 self.assertEqual(self._rootstring(result),
1467 _bytes('<A><y>Y</y><z/></A>'))
1468
1470 tree = self.parse('<a><b>B</b></a>')
1471 style = self.parse('''\
1472 <xsl:stylesheet version="1.0"
1473 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1474 xmlns:myns="testns"
1475 extension-element-prefixes="myns">
1476 <xsl:template match="a">
1477 <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
1478 </xsl:template>
1479 <xsl:template match="x" />
1480 <xsl:template match="z">XYZ</xsl:template>
1481 </xsl:stylesheet>''')
1482
1483 class MyExt(etree.XSLTExtension):
1484 def execute(self, context, self_node, input_node, output_parent):
1485 for child in self_node:
1486 for result in self.apply_templates(context, child):
1487 if isinstance(result, basestring):
1488 el = etree.Element("T")
1489 el.text = result
1490 else:
1491 el = result
1492 output_parent.append(el)
1493
1494 extensions = { ('testns', 'myext') : MyExt() }
1495
1496 result = tree.xslt(style, extensions=extensions)
1497 self.assertEqual(self._rootstring(result),
1498 _bytes('<A><T>Y</T><T>XYZ</T></A>'))
1499
1501 tree = self.parse('<a><b>B</b></a>')
1502 style = self.parse('''\
1503 <xsl:stylesheet version="1.0"
1504 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1505 xmlns:myns="testns"
1506 extension-element-prefixes="myns">
1507 <xsl:template match="a">
1508 <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
1509 </xsl:template>
1510 <xsl:template match="x" />
1511 <xsl:template match="z">XYZ</xsl:template>
1512 </xsl:stylesheet>''')
1513
1514 class MyExt(etree.XSLTExtension):
1515 def execute(self, context, self_node, input_node, output_parent):
1516 for child in self_node:
1517 self.apply_templates(context, child, output_parent)
1518
1519 extensions = { ('testns', 'myext') : MyExt() }
1520
1521 result = tree.xslt(style, extensions=extensions)
1522 self.assertEqual(self._rootstring(result),
1523 _bytes('<A>YXYZ</A>'))
1524
1526 tree = self.parse('<a><b>B</b></a>')
1527 style = self.parse('''\
1528 <xsl:stylesheet version="1.0"
1529 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1530 xmlns:myns="testns"
1531 extension-element-prefixes="myns">
1532 <xsl:template match="a">
1533 <myns:myext><x>X</x><y>Y</y><z/></myns:myext>
1534 </xsl:template>
1535 <xsl:template match="x"><xsl:processing-instruction name="test">TEST</xsl:processing-instruction></xsl:template>
1536 <xsl:template match="y"><Y>XYZ</Y></xsl:template>
1537 <xsl:template match="z"><xsl:comment>TEST</xsl:comment></xsl:template>
1538 </xsl:stylesheet>''')
1539
1540 class MyExt(etree.XSLTExtension):
1541 def execute(self, context, self_node, input_node, output_parent):
1542 for child in self_node:
1543 self.apply_templates(context, child, output_parent)
1544
1545 extensions = { ('testns', 'myext') : MyExt() }
1546
1547 result = tree.xslt(style, extensions=extensions)
1548 self.assertEqual(etree.tostring(result),
1549 _bytes('<?test TEST?><Y>XYZ</Y><!--TEST-->'))
1550
1552 tree = self.parse('<a><b>E</b></a>')
1553 style = self.parse('''\
1554 <xsl:stylesheet version="1.0"
1555 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1556 xmlns:myns="testns"
1557 extension-element-prefixes="myns">
1558 <xsl:template match="a">
1559 <xsl:variable name="testvar">yo</xsl:variable>
1560 <A>
1561 <myns:myext>
1562 <xsl:attribute name="attr">
1563 <xsl:value-of select="$testvar" />
1564 </xsl:attribute>
1565 <B>
1566 <xsl:choose>
1567 <xsl:when test="1 = 2"><C/></xsl:when>
1568 <xsl:otherwise><D><xsl:value-of select="b/text()" /></D></xsl:otherwise>
1569 </xsl:choose>
1570 </B>
1571 </myns:myext>
1572 </A>
1573 </xsl:template>
1574 </xsl:stylesheet>''')
1575
1576 class MyExt(etree.XSLTExtension):
1577 def execute(self, context, self_node, input_node, output_parent):
1578 el = etree.Element('MY')
1579 self.process_children(context, el)
1580 output_parent.append(el)
1581
1582 extensions = { ('testns', 'myext') : MyExt() }
1583
1584 result = tree.xslt(style, extensions=extensions)
1585 self.assertEqual(self._rootstring(result),
1586 _bytes('<A><MYattr="yo"><B><D>E</D></B></MY></A>'))
1587
1589 tree = self.parse('<a/>')
1590 style = self.parse('''\
1591 <xsl:stylesheet version="1.0"
1592 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1593 xmlns:myns="testns"
1594 extension-element-prefixes="myns">
1595 <xsl:template match="a">
1596 <myns:myext>
1597 <A/>
1598 </myns:myext>
1599 </xsl:template>
1600 </xsl:stylesheet>''')
1601
1602 class MyExt(etree.XSLTExtension):
1603 def execute(self, context, self_node, input_node, output_parent):
1604 self.process_children(context, output_parent)
1605
1606 extensions = { ('testns', 'myext') : MyExt() }
1607
1608 result = tree.xslt(style, extensions=extensions)
1609 self.assertEqual(self._rootstring(result),
1610 _bytes('<A/>'))
1611
1613 tree = self.parse('<a/>')
1614 style = self.parse('''\
1615 <xsl:stylesheet version="1.0"
1616 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1617 xmlns:myns="testns"
1618 extension-element-prefixes="myns">
1619 <xsl:template match="a">
1620 <myns:myext>
1621 <A/>
1622 </myns:myext>
1623 </xsl:template>
1624 </xsl:stylesheet>''')
1625
1626 class MyExt(etree.XSLTExtension):
1627 def execute(self, context, self_node, input_node, output_parent):
1628 self.process_children(context, self_node)
1629
1630 extensions = { ('testns', 'myext') : MyExt() }
1631
1632 self.assertRaises(TypeError, tree.xslt, style, extensions=extensions)
1633
1635 tree = self.parse('<a/>')
1636 style = self.parse('''\
1637 <xsl:stylesheet version="1.0"
1638 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1639 xmlns:myns="testns"
1640 extension-element-prefixes="myns">
1641 <xsl:template match="a">
1642 <myns:myext>
1643 <A><myns:myext><B/></myns:myext></A>
1644 </myns:myext>
1645 </xsl:template>
1646 </xsl:stylesheet>''')
1647
1648 class MyExt(etree.XSLTExtension):
1649 callback_call_counter = 0
1650 def execute(self, context, self_node, input_node, output_parent):
1651 self.callback_call_counter += 1
1652 el = etree.Element('MY', n=str(self.callback_call_counter))
1653 self.process_children(context, el)
1654 output_parent.append(el)
1655
1656 extensions = { ('testns', 'myext') : MyExt() }
1657
1658 result = tree.xslt(style, extensions=extensions)
1659 self.assertEqual(self._rootstring(result),
1660 _bytes('<MYn="1"><A><MYn="2"><B/></MY></A></MY>'))
1661
1663 tree = self.parse('<a><b>B</b></a>')
1664 style = self.parse('''\
1665 <xsl:stylesheet version="1.0"
1666 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1667 xmlns:myns="testns"
1668 extension-element-prefixes="myns"
1669 exclude-result-prefixes="myns">
1670 <xsl:template match="a">
1671 <A><myns:myext>b</myns:myext></A>
1672 </xsl:template>
1673 </xsl:stylesheet>''')
1674
1675 class MyError(Exception):
1676 pass
1677
1678 class MyExt(etree.XSLTExtension):
1679 def execute(self, context, self_node, input_node, output_parent):
1680 raise MyError("expected!")
1681
1682 extensions = { ('testns', 'myext') : MyExt() }
1683 self.assertRaises(MyError, tree.xslt, style, extensions=extensions)
1684
1685
1687 """XSLT tests for etree under Python 3"""
1688
1689 pytestmark = skipif('sys.version_info < (3,0)')
1690
1692 tree = self.parse('<a><b>B</b><c>C</c></a>')
1693 style = self.parse('''\
1694 <xsl:stylesheet version="1.0"
1695 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1696 <xsl:template match="*" />
1697 <xsl:template match="/">
1698 <foo><xsl:value-of select="/a/b/text()" /></foo>
1699 </xsl:template>
1700 </xsl:stylesheet>''')
1701
1702 st = etree.XSLT(style)
1703 res = st(tree)
1704 self.assertEqual(_bytes('''\
1705 <?xml version="1.0"?>
1706 <foo>B</foo>
1707 '''),
1708 bytes(res))
1709
1711 tree = self.parse('<a><b>B</b><c>C</c></a>')
1712 style = self.parse('''\
1713 <xsl:stylesheet version="1.0"
1714 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1715 <xsl:template match="*" />
1716 <xsl:template match="/">
1717 <foo><xsl:value-of select="/a/b/text()" /></foo>
1718 </xsl:template>
1719 </xsl:stylesheet>''')
1720
1721 st = etree.XSLT(style)
1722 res = st(tree)
1723 self.assertEqual(_bytes('''\
1724 <?xml version="1.0"?>
1725 <foo>B</foo>
1726 '''),
1727 bytearray(res))
1728
1730 tree = self.parse('<a><b>B</b><c>C</c></a>')
1731 style = self.parse('''\
1732 <xsl:stylesheet version="1.0"
1733 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1734 <xsl:template match="*" />
1735 <xsl:template match="/">
1736 <foo><xsl:value-of select="/a/b/text()" /></foo>
1737 </xsl:template>
1738 </xsl:stylesheet>''')
1739
1740 st = etree.XSLT(style)
1741 res = st(tree)
1742 self.assertEqual(_bytes('''\
1743 <?xml version="1.0"?>
1744 <foo>B</foo>
1745 '''),
1746 bytes(memoryview(res)))
1747
1748
1762
1763 if __name__ == '__main__':
1764 print('to test use test.py %s' % __file__)
1765