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