1
2
3 """
4 Test cases related to XSLT processing
5 """
6
7 import unittest, copy, sys, os.path
8
9 this_dir = os.path.dirname(__file__)
10 if this_dir not in sys.path:
11 sys.path.insert(0, this_dir)
12
13 is_python3 = sys.version_info[0] >= 3
14
15 try:
16 unicode = __builtins__["unicode"]
17 except (NameError, KeyError):
18 unicode = str
19
20 try:
21 basestring = __builtins__["basestring"]
22 except (NameError, KeyError):
23 basestring = str
24
25 from common_imports import etree, BytesIO, HelperTestCase, fileInTestDir
26 from common_imports import doctest, _bytes, _str, make_doctest
27
29 """XSLT tests etree"""
30
32 tree = self.parse('<a><b>B</b><c>C</c></a>')
33 style = self.parse('''\
34 <xsl:stylesheet version="1.0"
35 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
36 <xsl:template match="*" />
37 <xsl:template match="/">
38 <foo><xsl:value-of select="/a/b/text()" /></foo>
39 </xsl:template>
40 </xsl:stylesheet>''')
41
42 st = etree.XSLT(style)
43 res = st(tree)
44 self.assertEquals('''\
45 <?xml version="1.0"?>
46 <foo>B</foo>
47 ''',
48 str(res))
49
52
55
56 if False and etree.LIBXSLT_VERSION >= (1,1,15):
57
58 if etree.LIBXSLT_VERSION > (1,1,17):
60 style = self.parse('''\
61 <xsl:stylesheet version="1.0"
62 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
63 <xsl:stylesheet />
64 </xsl:stylesheet>''')
65
66 self.assertRaises(
67 etree.XSLTParseError, etree.XSLT, style)
68
70 tree = self.parse('<a><b>B</b><c>C</c></a>')
71 style = self.parse('''\
72 <xsl:stylesheet version="1.0"
73 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
74 <xsl:template match="*" />
75 <xsl:template match="/">
76 <foo><xsl:value-of select="/a/b/text()" /></foo>
77 </xsl:template>
78 </xsl:stylesheet>''')
79
80 transform = etree.XSLT(style)
81 res = transform(tree)
82 self.assertEquals('''\
83 <?xml version="1.0"?>
84 <foo>B</foo>
85 ''',
86 str(res))
87
88 transform_copy = copy.deepcopy(transform)
89 res = transform_copy(tree)
90 self.assertEquals('''\
91 <?xml version="1.0"?>
92 <foo>B</foo>
93 ''',
94 str(res))
95
96 transform = etree.XSLT(style)
97 res = transform(tree)
98 self.assertEquals('''\
99 <?xml version="1.0"?>
100 <foo>B</foo>
101 ''',
102 str(res))
103
105 tree = self.parse(_bytes('<a><b>\\uF8D2</b><c>\\uF8D2</c></a>'
106 ).decode("unicode_escape"))
107 style = self.parse('''\
108 <xsl:stylesheet version="1.0"
109 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
110 <xsl:output encoding="UTF-8"/>
111 <xsl:template match="/">
112 <foo><xsl:value-of select="/a/b/text()" /></foo>
113 </xsl:template>
114 </xsl:stylesheet>''')
115
116 st = etree.XSLT(style)
117 res = st(tree)
118 expected = _bytes('''\
119 <?xml version="1.0" encoding="UTF-8"?>
120 <foo>\\uF8D2</foo>
121 ''').decode("unicode_escape")
122 if is_python3:
123 self.assertEquals(expected,
124 str(bytes(res), 'UTF-8'))
125 else:
126 self.assertEquals(expected,
127 unicode(str(res), 'UTF-8'))
128
130 tree = self.parse(_bytes('<a><b>\\uF8D2</b><c>\\uF8D2</c></a>'
131 ).decode("unicode_escape"))
132 style = self.parse('''\
133 <xsl:stylesheet version="1.0"
134 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
135 <xsl:output encoding="UTF-16"/>
136 <xsl:template match="/">
137 <foo><xsl:value-of select="/a/b/text()" /></foo>
138 </xsl:template>
139 </xsl:stylesheet>''')
140
141 st = etree.XSLT(style)
142 res = st(tree)
143 expected = _bytes('''\
144 <?xml version="1.0" encoding="UTF-16"?>
145 <foo>\\uF8D2</foo>
146 ''').decode("unicode_escape")
147 if is_python3:
148 self.assertEquals(expected,
149 str(bytes(res), 'UTF-16'))
150 else:
151 self.assertEquals(expected,
152 unicode(str(res), 'UTF-16'))
153
155 tree = self.parse(_bytes('<a><b>\\uF8D2</b><c>\\uF8D2</c></a>'
156 ).decode("unicode_escape"))
157 style = self.parse('''\
158 <xsl:stylesheet version="1.0"
159 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
160 <xsl:output encoding="UTF-8"/>
161 <xsl:template match="/">
162 <foo><xsl:value-of select="/a/b/text()" /></foo>
163 </xsl:template>
164 </xsl:stylesheet>''')
165
166 st = etree.XSLT(style)
167 res = st(tree)
168 expected = _bytes("""\
169 <?xml version='1.0' encoding='UTF-16'?>\
170 <foo>\\uF8D2</foo>""").decode("unicode_escape")
171
172 f = BytesIO()
173 res.write(f, encoding='UTF-16')
174 if is_python3:
175 result = str(f.getvalue(), 'UTF-16').replace('\n', '')
176 else:
177 result = unicode(str(f.getvalue()), 'UTF-16').replace('\n', '')
178 self.assertEquals(expected, result)
179
181 tree = self.parse(_bytes('<a><b>\\uF8D2</b><c>\\uF8D2</c></a>'
182 ).decode("unicode_escape"))
183 style = self.parse('''\
184 <xsl:stylesheet version="1.0"
185 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
186 <xsl:output encoding="UTF-16"/>
187 <xsl:template match="/">
188 <foo><xsl:value-of select="/a/b/text()" /></foo>
189 </xsl:template>
190 </xsl:stylesheet>''')
191
192 st = etree.XSLT(style)
193 res = st(tree)
194 expected = _bytes('''\
195 <?xml version="1.0"?>
196 <foo>\\uF8D2</foo>
197 ''').decode("unicode_escape")
198 self.assertEquals(expected,
199 unicode(res))
200
202 tree = self.parse('<a><b>B</b><c>C</c></a>')
203 style = self.parse('''\
204 <xsl:stylesheet version="1.0"
205 xmlns:str="http://exslt.org/strings"
206 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
207 exclude-result-prefixes="str xsl">
208 <xsl:template match="text()">
209 <xsl:value-of select="str:align(string(.), '***', 'center')" />
210 </xsl:template>
211 <xsl:template match="*">
212 <xsl:copy>
213 <xsl:apply-templates/>
214 </xsl:copy>
215 </xsl:template>
216 </xsl:stylesheet>''')
217
218 st = etree.XSLT(style)
219 res = st(tree)
220 self.assertEquals('''\
221 <?xml version="1.0"?>
222 <a><b>*B*</b><c>*C*</c></a>
223 ''',
224 str(res))
225
226 if etree.LIBXSLT_VERSION >= (1,1,21):
228 tree = self.parse('<a><b>B</b><c>C</c></a>')
229 style = self.parse('''\
230 <xsl:stylesheet version = "1.0"
231 xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
232 xmlns:str="http://exslt.org/strings"
233 extension-element-prefixes="str">
234
235 <xsl:template match="/">
236 <h1 class="{str:replace('abc', 'b', 'x')}">test</h1>
237 </xsl:template>
238
239 </xsl:stylesheet>''')
240
241 st = etree.XSLT(style)
242 res = st(tree)
243 self.assertEquals('''\
244 <?xml version="1.0"?>
245 <h1 class="axc">test</h1>
246 ''',
247 str(res))
248
250 tree = self.parse('<a><b>B</b><c>C</c></a>')
251 style = self.parse('''\
252 <xsl:stylesheet version="1.0"
253 xmlns:math="http://exslt.org/math"
254 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
255 exclude-result-prefixes="math xsl">
256 <xsl:template match="*">
257 <xsl:copy>
258 <xsl:attribute name="pi">
259 <xsl:value-of select="math:constant('PI', count(*)+2)"/>
260 </xsl:attribute>
261 <xsl:apply-templates/>
262 </xsl:copy>
263 </xsl:template>
264 </xsl:stylesheet>''')
265
266 st = etree.XSLT(style)
267 res = st(tree)
268 self.assertEquals('''\
269 <?xml version="1.0"?>
270 <a pi="3.14"><b pi="3">B</b><c pi="3">C</c></a>
271 ''',
272 str(res))
273
286
303
305 tree = self.parse('<a/>')
306 style = self.parse('''\
307 <xsl:stylesheet version="1.0"
308 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
309 <xsl:foo />
310 </xsl:stylesheet>''')
311 self.assertRaises(etree.XSLTParseError,
312 etree.XSLT, style)
313
315 tree = self.parse('<a><b>B</b><c>C</c></a>')
316 style = self.parse('''\
317 <xsl:stylesheet version="1.0"
318 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
319 <xsl:template match="/">
320 <foo><xsl:value-of select="$bar" /></foo>
321 </xsl:template>
322 </xsl:stylesheet>''')
323
324 st = etree.XSLT(style)
325 res = st(tree, bar="'Bar'")
326 self.assertEquals('''\
327 <?xml version="1.0"?>
328 <foo>Bar</foo>
329 ''',
330 str(res))
331
333 tree = self.parse('<a><b>B</b><c>C</c></a>')
334 style = self.parse('''\
335 <xsl:stylesheet version="1.0"
336 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
337 <xsl:template match="/">
338 <foo><xsl:value-of select="$bar" /></foo>
339 </xsl:template>
340 </xsl:stylesheet>''')
341
342 st = etree.XSLT(style)
343 res = st(tree, bar=etree.XSLT.strparam('''it's me, "Bar"'''))
344 self.assertEquals('''\
345 <?xml version="1.0"?>
346 <foo>it's me, "Bar"</foo>
347 ''',
348 str(res))
349
351 tree = self.parse('<a><b>B</b><c>C</c></a>')
352 style = self.parse('''\
353 <xsl:stylesheet version="1.0"
354 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
355 <xsl:param name="bar"/>
356 <xsl:template match="/">
357 <foo><xsl:value-of select="$bar" /></foo>
358 </xsl:template>
359 </xsl:stylesheet>''')
360
361 st = etree.XSLT(style)
362 res = self.assertRaises(etree.XSLTApplyError,
363 st, tree, bar="<test/>")
364 res = self.assertRaises(etree.XSLTApplyError,
365 st, tree, bar="....")
366
367 if etree.LIBXSLT_VERSION < (1,1,18):
368
370
371 tree = self.parse('<a><b>B</b><c>C</c></a>')
372 style = self.parse('''\
373 <xsl:stylesheet version="1.0"
374 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
375 <xsl:template match="/">
376 <foo><xsl:value-of select="$bar" /></foo>
377 </xsl:template>
378 </xsl:stylesheet>''')
379
380 st = etree.XSLT(style)
381 self.assertRaises(etree.XSLTApplyError,
382 st.apply, tree)
383
385 tree = self.parse('<a><b>B</b><c>C</c></a>')
386 style = self.parse('''\
387 <xsl:stylesheet version="1.0"
388 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
389 <xsl:template match="*" />
390 <xsl:template match="/">
391 <foo><xsl:value-of select="$bar" /></foo>
392 <foo><xsl:value-of select="$baz" /></foo>
393 </xsl:template>
394 </xsl:stylesheet>''')
395
396 st = etree.XSLT(style)
397 res = st(tree, bar="'Bar'", baz="'Baz'")
398 self.assertEquals('''\
399 <?xml version="1.0"?>
400 <foo>Bar</foo><foo>Baz</foo>
401 ''',
402 str(res))
403
405 tree = self.parse('<a><b>B</b><c>C</c></a>')
406 style = self.parse('''\
407 <xsl:stylesheet version="1.0"
408 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
409 <xsl:template match="*" />
410 <xsl:template match="/">
411 <foo><xsl:value-of select="$bar" /></foo>
412 </xsl:template>
413 </xsl:stylesheet>''')
414
415 st = etree.XSLT(style)
416 res = st(tree, bar="/a/b/text()")
417 self.assertEquals('''\
418 <?xml version="1.0"?>
419 <foo>B</foo>
420 ''',
421 str(res))
422
424 tree = self.parse('<a><b>B</b><c>C</c></a>')
425 style = self.parse('''\
426 <xsl:stylesheet version="1.0"
427 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
428 <xsl:template match="*" />
429 <xsl:template match="/">
430 <foo><xsl:value-of select="$bar" /></foo>
431 </xsl:template>
432 </xsl:stylesheet>''')
433
434 st = etree.XSLT(style)
435 res = st(tree, bar=etree.XPath("/a/b/text()"))
436 self.assertEquals('''\
437 <?xml version="1.0"?>
438 <foo>B</foo>
439 ''',
440 str(res))
441
443 tree = self.parse('<a><b>B</b><c>C</c></a>')
444 style = self.parse('''\
445 <xsl:stylesheet version="1.0"
446 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
447 <xsl:param name="bar" select="'Default'" />
448 <xsl:template match="*" />
449 <xsl:template match="/">
450 <foo><xsl:value-of select="$bar" /></foo>
451 </xsl:template>
452 </xsl:stylesheet>''')
453
454 st = etree.XSLT(style)
455 res = st(tree, bar="'Bar'")
456 self.assertEquals('''\
457 <?xml version="1.0"?>
458 <foo>Bar</foo>
459 ''',
460 str(res))
461 res = st(tree)
462 self.assertEquals('''\
463 <?xml version="1.0"?>
464 <foo>Default</foo>
465 ''',
466 str(res))
467
469 tree = self.parse('<a><b>B</b><c>C</c></a>')
470 style = self.parse('''\
471 <xsl:stylesheet version="1.0"
472 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
473 <xsl:output method="html"/>
474 <xsl:strip-space elements="*"/>
475 <xsl:template match="/">
476 <html><body><xsl:value-of select="/a/b/text()" /></body></html>
477 </xsl:template>
478 </xsl:stylesheet>''')
479
480 st = etree.XSLT(style)
481 res = st(tree)
482 self.assertEquals('<html><body>B</body></html>',
483 str(res).strip())
484
488
494
517
542
544
545 xml = '<blah/>'
546 xslt = '''
547 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
548 <xsl:template match="/" />
549 </xsl:stylesheet>
550 '''
551
552 source = self.parse(xml)
553 styledoc = self.parse(xslt)
554 style = etree.XSLT(styledoc)
555 result = style(source)
556 self.assertEqual('', str(result))
557
559 xml = '<blah/>'
560 xslt = '''
561 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
562 <xsl:template match="/">
563 <xsl:message>TEST TEST TEST</xsl:message>
564 </xsl:template>
565 </xsl:stylesheet>
566 '''
567
568 source = self.parse(xml)
569 styledoc = self.parse(xslt)
570 style = etree.XSLT(styledoc)
571 result = style(source)
572 self.assertEqual('', str(result))
573 self.assert_("TEST TEST TEST" in [entry.message
574 for entry in style.error_log])
575
577 xml = '<blah/>'
578 xslt = '''
579 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
580 <xsl:template match="/">
581 <xsl:message terminate="yes">TEST TEST TEST</xsl:message>
582 </xsl:template>
583 </xsl:stylesheet>
584 '''
585
586 source = self.parse(xml)
587 styledoc = self.parse(xslt)
588 style = etree.XSLT(styledoc)
589
590 self.assertRaises(etree.XSLTApplyError, style, source)
591 self.assert_("TEST TEST TEST" in [entry.message
592 for entry in style.error_log])
593
595 tree = self.parse('<a><b>B</b><c>C</c></a>')
596 style = self.parse('''\
597 <xsl:stylesheet version="1.0"
598 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
599 <xsl:template match="*" />
600 <xsl:template match="/">
601 <doc>
602 <foo><xsl:value-of select="$bar" /></foo>
603 <foo><xsl:value-of select="$baz" /></foo>
604 </doc>
605 </xsl:template>
606 </xsl:stylesheet>''')
607
608 result = tree.xslt(style, bar="'Bar'", baz="'Baz'")
609 self.assertEquals(
610 _bytes('<doc><foo>Bar</foo><foo>Baz</foo></doc>'),
611 etree.tostring(result.getroot()))
612
614 tree = self.parse('<a><b>B</b><c>C</c></a>')
615 style = self.parse('''\
616 <xsl:stylesheet version="1.0"
617 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
618 <xsl:template match="a"><A><xsl:apply-templates/></A></xsl:template>
619 <xsl:template match="b"><B><xsl:apply-templates/></B></xsl:template>
620 <xsl:template match="c"><C><xsl:apply-templates/></C></xsl:template>
621 </xsl:stylesheet>''')
622
623 self.assertEquals(self._rootstring(tree),
624 _bytes('<a><b>B</b><c>C</c></a>'))
625 result = tree.xslt(style)
626 self.assertEquals(self._rootstring(tree),
627 _bytes('<a><b>B</b><c>C</c></a>'))
628 self.assertEquals(self._rootstring(result),
629 _bytes('<A><B>B</B><C>C</C></A>'))
630
631 b_tree = etree.ElementTree(tree.getroot()[0])
632 self.assertEquals(self._rootstring(b_tree),
633 _bytes('<b>B</b>'))
634 result = b_tree.xslt(style)
635 self.assertEquals(self._rootstring(tree),
636 _bytes('<a><b>B</b><c>C</c></a>'))
637 self.assertEquals(self._rootstring(result),
638 _bytes('<B>B</B>'))
639
640 c_tree = etree.ElementTree(tree.getroot()[1])
641 self.assertEquals(self._rootstring(c_tree),
642 _bytes('<c>C</c>'))
643 result = c_tree.xslt(style)
644 self.assertEquals(self._rootstring(tree),
645 _bytes('<a><b>B</b><c>C</c></a>'))
646 self.assertEquals(self._rootstring(result),
647 _bytes('<C>C</C>'))
648
650
651 xslt = etree.XSLT(etree.XML("""\
652 <xsl:stylesheet version="1.0"
653 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
654 <xsl:template match="/">
655 <test>TEXT<xsl:copy-of select="document('')//test"/></test>
656 </xsl:template>
657 </xsl:stylesheet>
658 """))
659 result = xslt(etree.XML('<a/>'))
660 root = result.getroot()
661 self.assertEquals(root.tag,
662 'test')
663 self.assertEquals(root[0].tag,
664 'test')
665 self.assertEquals(root[0].text,
666 'TEXT')
667 self.assertEquals(root[0][0].tag,
668 '{http://www.w3.org/1999/XSL/Transform}copy-of')
669
679
689
691 xslt = etree.XSLT(etree.XML("""\
692 <xsl:stylesheet version="1.0"
693 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
694 <xsl:template match="/">
695 <test>TEXT<xsl:copy-of select="document('uri:__junkfood__is__evil__')//test"/></test>
696 </xsl:template>
697 </xsl:stylesheet>
698 """))
699 self.assertRaises(etree.XSLTApplyError, xslt, etree.XML('<a/>'))
700
702
703 assertEquals = self.assertEquals
704 called = {'count' : 0}
705 class TestResolver(etree.Resolver):
706 def resolve(self, url, id, context):
707 assertEquals(url, 'file://ANYTHING')
708 called['count'] += 1
709 return self.resolve_string('<CALLED/>', context)
710
711 parser = etree.XMLParser()
712 parser.resolvers.add(TestResolver())
713
714 xslt = etree.XSLT(etree.XML(_bytes("""\
715 <xsl:stylesheet version="1.0"
716 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
717 xmlns:l="local">
718 <xsl:template match="/">
719 <test>
720 <xsl:for-each select="document('')//l:data/l:entry">
721 <xsl:copy-of select="document('file://ANYTHING')"/>
722 <xsl:copy>
723 <xsl:attribute name="value">
724 <xsl:value-of select="."/>
725 </xsl:attribute>
726 </xsl:copy>
727 </xsl:for-each>
728 </test>
729 </xsl:template>
730 <l:data>
731 <l:entry>A</l:entry>
732 <l:entry>B</l:entry>
733 </l:data>
734 </xsl:stylesheet>
735 """), parser))
736
737 self.assertEquals(called['count'], 0)
738 result = xslt(etree.XML('<a/>'))
739 self.assertEquals(called['count'], 1)
740
741 root = result.getroot()
742 self.assertEquals(root.tag,
743 'test')
744 self.assertEquals(len(root), 4)
745
746 self.assertEquals(root[0].tag,
747 'CALLED')
748 self.assertEquals(root[1].tag,
749 '{local}entry')
750 self.assertEquals(root[1].text,
751 None)
752 self.assertEquals(root[1].get("value"),
753 'A')
754 self.assertEquals(root[2].tag,
755 'CALLED')
756 self.assertEquals(root[3].tag,
757 '{local}entry')
758 self.assertEquals(root[3].text,
759 None)
760 self.assertEquals(root[3].get("value"),
761 'B')
762
764 assertEquals = self.assertEquals
765 called = {'count' : 0}
766 expected_url = None
767 class TestResolver(etree.Resolver):
768 def resolve(self, url, id, context):
769 assertEquals(url, expected_url)
770 called['count'] += 1
771 return self.resolve_string('<CALLED/>', context)
772
773 stylesheet_xml = _bytes("""\
774 <xsl:stylesheet version="1.0"
775 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
776 xmlns:l="local">
777 <xsl:template match="/">
778 <xsl:copy-of select="document('test.xml')"/>
779 </xsl:template>
780 </xsl:stylesheet>
781 """)
782
783 parser = etree.XMLParser()
784 parser.resolvers.add(TestResolver())
785
786
787 expected_url = 'test.xml'
788 xslt = etree.XSLT(etree.XML(stylesheet_xml, parser))
789
790 self.assertEquals(called['count'], 0)
791 result = xslt(etree.XML('<a/>'))
792 self.assertEquals(called['count'], 1)
793
794
795 called['count'] = 0
796 expected_url = os.path.join('MY', 'BASE', 'test.xml')
797 xslt = etree.XSLT(etree.XML(stylesheet_xml, parser,
798 base_url=os.path.join('MY', 'BASE', 'FILE')))
799
800 self.assertEquals(called['count'], 0)
801 result = xslt(etree.XML('<a/>'))
802 self.assertEquals(called['count'], 1)
803
804
805 called['count'] = 0
806 expected_url = 'http://server.com/BASE/DIR/test.xml'
807 xslt = etree.XSLT(etree.XML(stylesheet_xml, parser,
808 base_url='http://server.com/BASE/DIR/FILE'))
809
810 self.assertEquals(called['count'], 0)
811 result = xslt(etree.XML('<a/>'))
812 self.assertEquals(called['count'], 1)
813
824
830
836
838 root = etree.XML(_bytes('''\
839 <transform>
840 <widget displayType="fieldset"/>
841 </transform>'''))
842
843 xslt = etree.XSLT(etree.XML(_bytes('''\
844 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
845 <xsl:output method="html" indent="no"/>
846 <xsl:template match="/">
847 <html>
848 <xsl:apply-templates/>
849 </html>
850 </xsl:template>
851
852 <xsl:template match="widget">
853 <xsl:element name="{@displayType}"/>
854 </xsl:template>
855
856 </xsl:stylesheet>''')))
857
858 result = xslt(root[0])
859 root[:] = result.getroot()[:]
860 del root
861
863 tree = self.parse('''\
864 <?xml version="1.0"?>
865 <?xml-stylesheet type="text/xsl" href="%s"?>
866 <a>
867 <b>B</b>
868 <c>C</c>
869 </a>''' % fileInTestDir("test1.xslt"))
870
871 style_root = tree.getroot().getprevious().parseXSL().getroot()
872 self.assertEquals("{http://www.w3.org/1999/XSL/Transform}stylesheet",
873 style_root.tag)
874
876
877 tree = self.parse('''\
878 <?xml version="1.0"?>
879 <?xml-stylesheet type="text/xsl" href="#style"?>
880 <a>
881 <b>B</b>
882 <c>C</c>
883 <xsl:stylesheet version="1.0" xml:id="style"
884 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
885 <xsl:template match="*" />
886 <xsl:template match="/">
887 <foo><xsl:value-of select="/a/b/text()" /></foo>
888 </xsl:template>
889 </xsl:stylesheet>
890 </a>''')
891
892 style_root = tree.getroot().getprevious().parseXSL().getroot()
893 self.assertEquals("{http://www.w3.org/1999/XSL/Transform}stylesheet",
894 style_root.tag)
895
896 st = etree.XSLT(style_root)
897 res = st(tree)
898 self.assertEquals('''\
899 <?xml version="1.0"?>
900 <foo>B</foo>
901 ''',
902 str(res))
903
905
906 tree = self.parse('''\
907 <?xml version="1.0"?>
908 <?xml-stylesheet type="text/xsl" href="#style"?>
909 <a>
910 <b>B</b>
911 <c>C</c>
912 </a>''')
913
914 style = self.parse('''\
915 <xsl:stylesheet version="1.0" xml:id="style"
916 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
917 <xsl:template match="*" />
918 <xsl:template match="/">
919 <foo><xsl:value-of select="/a/b/text()" /></foo>
920 </xsl:template>
921 </xsl:stylesheet>
922 ''')
923
924 tree.getroot().append(style.getroot())
925
926 style_root = tree.getroot().getprevious().parseXSL().getroot()
927 self.assertEquals("{http://www.w3.org/1999/XSL/Transform}stylesheet",
928 style_root.tag)
929
930 st = etree.XSLT(style_root)
931 res = st(tree)
932 self.assertEquals('''\
933 <?xml version="1.0"?>
934 <foo>B</foo>
935 ''',
936 str(res))
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.assertEquals("TEST", pi.get("href"))
949
951 tree = self.parse('''\
952 <?xml version="1.0"?>
953 <?xml-stylesheet type="text/xsl" href="TEST"?>
954 <a>
955 <b>B</b>
956 <c>C</c>
957 </a>''')
958
959 pi = tree.getroot().getprevious()
960 self.assertEquals("TEST", pi.get("href"))
961 self.assertEquals("text/xsl", pi.get("type"))
962 self.assertEquals(None, pi.get("motz"))
963
965 tree = self.parse('''\
966 <?xml version="1.0"?>
967 <?xml-stylesheet href="TEST" type="text/xsl"?>
968 <a>
969 <b>B</b>
970 <c>C</c>
971 </a>''')
972
973 pi = tree.getroot().getprevious()
974 self.assertEquals("TEST", pi.get("href"))
975 self.assertEquals("text/xsl", pi.get("type"))
976 self.assertEquals(None, pi.get("motz"))
977
979 tree = self.parse('''\
980 <?xml version="1.0"?>
981 <?xml-stylesheet type="text/xsl" href="TEST"?>
982 <a>
983 <b>B</b>
984 <c>C</c>
985 </a>''')
986
987 pi = tree.getroot().getprevious()
988 self.assertEquals(None, pi.get("unknownattribute"))
989
991 tree = self.parse('''\
992 <?xml version="1.0"?>
993 <?xml-stylesheet type="text/xsl" href="TEST"?>
994 <a>
995 <b>B</b>
996 <c>C</c>
997 </a>''')
998
999 pi = tree.getroot().getprevious()
1000 self.assertEquals("TEST", pi.get("href"))
1001
1002 pi.set("href", "TEST123")
1003 self.assertEquals("TEST123", pi.get("href"))
1004
1006 tree = self.parse('''\
1007 <?xml version="1.0"?>
1008 <?xml-stylesheet type="text/xsl"?>
1009 <a>
1010 <b>B</b>
1011 <c>C</c>
1012 </a>''')
1013
1014 pi = tree.getroot().getprevious()
1015 self.assertEquals(None, pi.get("href"))
1016
1017 pi.set("href", "TEST")
1018 self.assertEquals("TEST", pi.get("href"))
1019
1021 xslt = etree.XSLT(etree.XML(_bytes("""\
1022 <xsl:stylesheet version="1.0"
1023 xmlns:regexp="http://exslt.org/regular-expressions"
1024 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1025 <xsl:template match="*">
1026 <test><xsl:copy-of select="*[regexp:test(string(.), '8.')]"/></test>
1027 </xsl:template>
1028 </xsl:stylesheet>
1029 """)))
1030 result = xslt(etree.XML(_bytes('<a><b>123</b><b>098</b><b>987</b></a>')))
1031 root = result.getroot()
1032 self.assertEquals(root.tag,
1033 'test')
1034 self.assertEquals(len(root), 1)
1035 self.assertEquals(root[0].tag,
1036 'b')
1037 self.assertEquals(root[0].text,
1038 '987')
1039
1041 xslt = etree.XSLT(etree.XML("""\
1042 <xsl:stylesheet version="1.0"
1043 xmlns:regexp="http://exslt.org/regular-expressions"
1044 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1045 <xsl:template match="*">
1046 <test>
1047 <xsl:copy-of select="regexp:replace(string(.), 'd.', '', 'XX')"/>
1048 <xsl:text>-</xsl:text>
1049 <xsl:copy-of select="regexp:replace(string(.), 'd.', 'gi', 'XX')"/>
1050 </test>
1051 </xsl:template>
1052 </xsl:stylesheet>
1053 """))
1054 result = xslt(etree.XML(_bytes('<a>abdCdEeDed</a>')))
1055 root = result.getroot()
1056 self.assertEquals(root.tag,
1057 'test')
1058 self.assertEquals(len(root), 0)
1059 self.assertEquals(root.text, 'abXXdEeDed-abXXXXeXXd')
1060
1062 xslt = etree.XSLT(etree.XML("""\
1063 <xsl:stylesheet version="1.0"
1064 xmlns:regexp="http://exslt.org/regular-expressions"
1065 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1066 <xsl:template match="*">
1067 <test>
1068 <test1><xsl:copy-of select="regexp:match(string(.), 'd.')"/></test1>
1069 <test2><xsl:copy-of select="regexp:match(string(.), 'd.', 'g')"/></test2>
1070 <test2i><xsl:copy-of select="regexp:match(string(.), 'd.', 'gi')"/></test2i>
1071 </test>
1072 </xsl:template>
1073 </xsl:stylesheet>
1074 """))
1075 result = xslt(etree.XML(_bytes('<a>abdCdEeDed</a>')))
1076 root = result.getroot()
1077 self.assertEquals(root.tag, 'test')
1078 self.assertEquals(len(root), 3)
1079
1080 self.assertEquals(len(root[0]), 1)
1081 self.assertEquals(root[0][0].tag, 'match')
1082 self.assertEquals(root[0][0].text, 'dC')
1083
1084 self.assertEquals(len(root[1]), 2)
1085 self.assertEquals(root[1][0].tag, 'match')
1086 self.assertEquals(root[1][0].text, 'dC')
1087 self.assertEquals(root[1][1].tag, 'match')
1088 self.assertEquals(root[1][1].text, 'dE')
1089
1090 self.assertEquals(len(root[2]), 3)
1091 self.assertEquals(root[2][0].tag, 'match')
1092 self.assertEquals(root[2][0].text, 'dC')
1093 self.assertEquals(root[2][1].tag, 'match')
1094 self.assertEquals(root[2][1].text, 'dE')
1095 self.assertEquals(root[2][2].tag, 'match')
1096 self.assertEquals(root[2][2].text, 'De')
1097
1099 xslt = etree.XSLT(etree.XML(_bytes("""\
1100 <xsl:stylesheet version="1.0"
1101 xmlns:regexp="http://exslt.org/regular-expressions"
1102 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1103 <xsl:template match="/">
1104 <test>
1105 <xsl:for-each select="regexp:match(
1106 '123abc567', '([0-9]+)([a-z]+)([0-9]+)' )">
1107 <test1><xsl:value-of select="."/></test1>
1108 </xsl:for-each>
1109 </test>
1110 </xsl:template>
1111 </xsl:stylesheet>
1112 """)))
1113 result = xslt(etree.XML(_bytes('<a/>')))
1114 root = result.getroot()
1115 self.assertEquals(root.tag, 'test')
1116 self.assertEquals(len(root), 4)
1117
1118 self.assertEquals(root[0].text, "123abc567")
1119 self.assertEquals(root[1].text, "123")
1120 self.assertEquals(root[2].text, "abc")
1121 self.assertEquals(root[3].text, "567")
1122
1124
1125 xslt = etree.XSLT(etree.XML(_bytes("""\
1126 <xsl:stylesheet version="1.0"
1127 xmlns:regexp="http://exslt.org/regular-expressions"
1128 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1129 <xsl:template match="/">
1130 <test>
1131 <xsl:for-each select="regexp:match(
1132 'http://www.bayes.co.uk/xml/index.xml?/xml/utils/rechecker.xml',
1133 '(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)')">
1134 <test1><xsl:value-of select="."/></test1>
1135 </xsl:for-each>
1136 </test>
1137 </xsl:template>
1138 </xsl:stylesheet>
1139 """)))
1140 result = xslt(etree.XML(_bytes('<a/>')))
1141 root = result.getroot()
1142 self.assertEquals(root.tag, 'test')
1143 self.assertEquals(len(root), 5)
1144
1145 self.assertEquals(
1146 root[0].text,
1147 "http://www.bayes.co.uk/xml/index.xml?/xml/utils/rechecker.xml")
1148 self.assertEquals(
1149 root[1].text,
1150 "http")
1151 self.assertEquals(
1152 root[2].text,
1153 "www.bayes.co.uk")
1154 self.assertFalse(root[3].text)
1155 self.assertEquals(
1156 root[4].text,
1157 "/xml/index.xml?/xml/utils/rechecker.xml")
1158
1160
1161 xslt = etree.XSLT(self.parse("""\
1162 <xsl:stylesheet version="1.0"
1163 xmlns:regexp="http://exslt.org/regular-expressions"
1164 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1165 <xsl:template match="/">
1166 <test>
1167 <xsl:for-each select="regexp:match(
1168 'This is a test string', '(\w+)', 'g')">
1169 <test1><xsl:value-of select="."/></test1>
1170 </xsl:for-each>
1171 </test>
1172 </xsl:template>
1173 </xsl:stylesheet>
1174 """))
1175 result = xslt(etree.XML(_bytes('<a/>')))
1176 root = result.getroot()
1177 self.assertEquals(root.tag, 'test')
1178 self.assertEquals(len(root), 5)
1179
1180 self.assertEquals(root[0].text, "This")
1181 self.assertEquals(root[1].text, "is")
1182 self.assertEquals(root[2].text, "a")
1183 self.assertEquals(root[3].text, "test")
1184 self.assertEquals(root[4].text, "string")
1185
1187
1188
1189 xslt = etree.XSLT(etree.XML(_bytes("""\
1190 <xsl:stylesheet version="1.0"
1191 xmlns:regexp="http://exslt.org/regular-expressions"
1192 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1193 <xsl:template match="/">
1194 <test>
1195 <xsl:for-each select="regexp:match(
1196 'This is a test string', '([a-z])+ ', 'g')">
1197 <test1><xsl:value-of select="."/></test1>
1198 </xsl:for-each>
1199 </test>
1200 </xsl:template>
1201 </xsl:stylesheet>
1202 """)))
1203 result = xslt(etree.XML(_bytes('<a/>')))
1204 root = result.getroot()
1205 self.assertEquals(root.tag, 'test')
1206 self.assertEquals(len(root), 4)
1207
1208 self.assertEquals(root[0].text, "his")
1209 self.assertEquals(root[1].text, "is")
1210 self.assertEquals(root[2].text, "a")
1211 self.assertEquals(root[3].text, "test")
1212
1214
1215
1216 xslt = etree.XSLT(etree.XML(_bytes("""\
1217 <xsl:stylesheet version="1.0"
1218 xmlns:regexp="http://exslt.org/regular-expressions"
1219 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1220 <xsl:template match="/">
1221 <test>
1222 <xsl:for-each select="regexp:match(
1223 'This is a test string', '([a-z])+ ', 'gi')">
1224 <test1><xsl:value-of select="."/></test1>
1225 </xsl:for-each>
1226 </test>
1227 </xsl:template>
1228 </xsl:stylesheet>
1229 """)))
1230 result = xslt(etree.XML(_bytes('<a/>')))
1231 root = result.getroot()
1232 self.assertEquals(root.tag, 'test')
1233 self.assertEquals(len(root), 4)
1234
1235 self.assertEquals(root[0].text, "This")
1236 self.assertEquals(root[1].text, "is")
1237 self.assertEquals(root[2].text, "a")
1238 self.assertEquals(root[3].text, "test")
1239
1240
1241 -class ETreeXSLTExtFuncTestCase(HelperTestCase):
1242 """Tests for XPath extension functions in XSLT."""
1243
1244 - def test_extensions1(self):
1245 tree = self.parse('<a><b>B</b></a>')
1246 style = self.parse('''\
1247 <xsl:stylesheet version="1.0"
1248 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1249 xmlns:myns="testns"
1250 exclude-result-prefixes="myns">
1251 <xsl:template match="a"><A><xsl:value-of select="myns:mytext(b)"/></A></xsl:template>
1252 </xsl:stylesheet>''')
1253
1254 def mytext(ctxt, values):
1255 return 'X' * len(values)
1256
1257 result = tree.xslt(style, {('testns', 'mytext') : mytext})
1258 self.assertEquals(self._rootstring(result),
1259 _bytes('<A>X</A>'))
1260
1261 - def test_extensions2(self):
1262 tree = self.parse('<a><b>B</b></a>')
1263 style = self.parse('''\
1264 <xsl:stylesheet version="1.0"
1265 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1266 xmlns:myns="testns"
1267 exclude-result-prefixes="myns">
1268 <xsl:template match="a"><A><xsl:value-of select="myns:mytext(b)"/></A></xsl:template>
1269 </xsl:stylesheet>''')
1270
1271 def mytext(ctxt, values):
1272 return 'X' * len(values)
1273
1274 namespace = etree.FunctionNamespace('testns')
1275 namespace['mytext'] = mytext
1276
1277 result = tree.xslt(style)
1278 self.assertEquals(self._rootstring(result),
1279 _bytes('<A>X</A>'))
1280
1282 tree = self.parse('<a><b>B</b><b/></a>')
1283 style = self.parse('''\
1284 <xsl:stylesheet version="1.0"
1285 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1286 xmlns:myns="testns"
1287 exclude-result-prefixes="myns">
1288 <xsl:template match="a">
1289 <xsl:variable name="content">
1290 <xsl:apply-templates/>
1291 </xsl:variable>
1292 <A><xsl:value-of select="myns:mytext($content)"/></A>
1293 </xsl:template>
1294 <xsl:template match="b"><xsl:copy>BBB</xsl:copy></xsl:template>
1295 </xsl:stylesheet>''')
1296
1297 def mytext(ctxt, values):
1298 for value in values:
1299 self.assert_(hasattr(value, 'tag'),
1300 "%s is not an Element" % type(value))
1301 self.assertEquals(value.tag, 'b')
1302 self.assertEquals(value.text, 'BBB')
1303 return 'X'.join([el.tag for el in values])
1304
1305 namespace = etree.FunctionNamespace('testns')
1306 namespace['mytext'] = mytext
1307
1308 result = tree.xslt(style)
1309 self.assertEquals(self._rootstring(result),
1310 _bytes('<A>bXb</A>'))
1311
1312
1313 -class ETreeXSLTExtElementTestCase(HelperTestCase):
1314 """Tests for extension elements in XSLT."""
1315
1317 tree = self.parse('<a><b>B</b></a>')
1318 style = self.parse('''\
1319 <xsl:stylesheet version="1.0"
1320 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1321 xmlns:myns="testns"
1322 extension-element-prefixes="myns"
1323 exclude-result-prefixes="myns">
1324 <xsl:template match="a">
1325 <A><myns:myext>b</myns:myext></A>
1326 </xsl:template>
1327 </xsl:stylesheet>''')
1328
1329 class MyExt(etree.XSLTExtension):
1330 def execute(self, context, self_node, input_node, output_parent):
1331 child = etree.Element(self_node.text)
1332 child.text = 'X'
1333 output_parent.append(child)
1334
1335 extensions = { ('testns', 'myext') : MyExt() }
1336
1337 result = tree.xslt(style, extensions=extensions)
1338 self.assertEquals(self._rootstring(result),
1339 _bytes('<A><b>X</b></A>'))
1340
1342 tree = self.parse('<a><b>B</b></a>')
1343 style = self.parse('''\
1344 <xsl:stylesheet version="1.0"
1345 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1346 xmlns:myns="testns"
1347 extension-element-prefixes="myns"
1348 exclude-result-prefixes="myns">
1349 <xsl:template match="/">
1350 <A><myns:myext>b</myns:myext></A>
1351 </xsl:template>
1352 </xsl:stylesheet>''')
1353
1354 tags = []
1355
1356 class MyExt(etree.XSLTExtension):
1357 def execute(self, context, self_node, input_node, output_parent):
1358 tags.append(input_node.tag)
1359
1360 extensions = { ('testns', 'myext') : MyExt() }
1361
1362 result = tree.xslt(style, extensions=extensions)
1363 self.assertEquals(tags, ['a'])
1364
1366 tree = self.parse('<?test toast?><a><!--a comment--><?another pi?></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 <ROOT><xsl:apply-templates /></ROOT>
1375 </xsl:template>
1376 <xsl:template match="comment()">
1377 <A><myns:myext>b</myns:myext></A>
1378 </xsl:template>
1379 <xsl:template match="processing-instruction()">
1380 <A><myns:myext>b</myns:myext></A>
1381 </xsl:template>
1382 </xsl:stylesheet>''')
1383
1384 text = []
1385
1386 class MyExt(etree.XSLTExtension):
1387 def execute(self, context, self_node, input_node, output_parent):
1388 text.append(input_node.text)
1389
1390 extensions = { ('testns', 'myext') : MyExt() }
1391
1392 result = tree.xslt(style, extensions=extensions)
1393 self.assertEquals(text, ['toast', 'a comment', 'pi'])
1394
1396
1397 tree = self.parse('<a test="A"><b attr="B"/></a>')
1398 style = self.parse('''\
1399 <xsl:stylesheet version="1.0"
1400 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1401 xmlns:myns="testns"
1402 extension-element-prefixes="myns"
1403 exclude-result-prefixes="myns">
1404 <xsl:template match="@test">
1405 <A><myns:myext>b</myns:myext></A>
1406 </xsl:template>
1407 <xsl:template match="@attr">
1408 <A><myns:myext>b</myns:myext></A>
1409 </xsl:template>
1410 </xsl:stylesheet>''')
1411
1412 text = []
1413
1414 class MyExt(etree.XSLTExtension):
1415 def execute(self, context, self_node, attr_value, output_parent):
1416 text.append(attr_value)
1417
1418 extensions = { ('testns', 'myext') : MyExt() }
1419
1420 result = tree.xslt(style, extensions=extensions)
1421 self.assertEquals(text, ['A', 'B'])
1422
1424 tree = self.parse('<a><b>B</b></a>')
1425 style = self.parse('''\
1426 <xsl:stylesheet version="1.0"
1427 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1428 xmlns:myns="testns"
1429 extension-element-prefixes="myns">
1430 <xsl:template match="a">
1431 <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
1432 </xsl:template>
1433 </xsl:stylesheet>''')
1434
1435 class MyExt(etree.XSLTExtension):
1436 def execute(self, context, self_node, input_node, output_parent):
1437 output_parent.extend(list(self_node)[1:])
1438
1439 extensions = { ('testns', 'myext') : MyExt() }
1440
1441 result = tree.xslt(style, extensions=extensions)
1442 self.assertEquals(self._rootstring(result),
1443 _bytes('<A><y>Y</y><z/></A>'))
1444
1446 tree = self.parse('<a><b>B</b></a>')
1447 style = self.parse('''\
1448 <xsl:stylesheet version="1.0"
1449 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1450 xmlns:myns="testns"
1451 extension-element-prefixes="myns">
1452 <xsl:template match="a">
1453 <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
1454 </xsl:template>
1455 <xsl:template match="x" />
1456 <xsl:template match="z">XYZ</xsl:template>
1457 </xsl:stylesheet>''')
1458
1459 class MyExt(etree.XSLTExtension):
1460 def execute(self, context, self_node, input_node, output_parent):
1461 for child in self_node:
1462 for result in self.apply_templates(context, child):
1463 if isinstance(result, basestring):
1464 el = etree.Element("T")
1465 el.text = result
1466 else:
1467 el = result
1468 output_parent.append(el)
1469
1470 extensions = { ('testns', 'myext') : MyExt() }
1471
1472 result = tree.xslt(style, extensions=extensions)
1473 self.assertEquals(self._rootstring(result),
1474 _bytes('<A><T>Y</T><T>XYZ</T></A>'))
1475
1477 tree = self.parse('<a><b>B</b></a>')
1478 style = self.parse('''\
1479 <xsl:stylesheet version="1.0"
1480 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1481 xmlns:myns="testns"
1482 extension-element-prefixes="myns">
1483 <xsl:template match="a">
1484 <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
1485 </xsl:template>
1486 <xsl:template match="x" />
1487 <xsl:template match="z">XYZ</xsl:template>
1488 </xsl:stylesheet>''')
1489
1490 class MyExt(etree.XSLTExtension):
1491 def execute(self, context, self_node, input_node, output_parent):
1492 for child in self_node:
1493 self.apply_templates(context, child, output_parent)
1494
1495 extensions = { ('testns', 'myext') : MyExt() }
1496
1497 result = tree.xslt(style, extensions=extensions)
1498 self.assertEquals(self._rootstring(result),
1499 _bytes('<A>YXYZ</A>'))
1500
1502 tree = self.parse('<a><b>B</b></a>')
1503 style = self.parse('''\
1504 <xsl:stylesheet version="1.0"
1505 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1506 xmlns:myns="testns"
1507 extension-element-prefixes="myns">
1508 <xsl:template match="a">
1509 <myns:myext><x>X</x><y>Y</y><z/></myns:myext>
1510 </xsl:template>
1511 <xsl:template match="x"><xsl:processing-instruction name="test">TEST</xsl:processing-instruction></xsl:template>
1512 <xsl:template match="y"><Y>XYZ</Y></xsl:template>
1513 <xsl:template match="z"><xsl:comment>TEST</xsl:comment></xsl:template>
1514 </xsl:stylesheet>''')
1515
1516 class MyExt(etree.XSLTExtension):
1517 def execute(self, context, self_node, input_node, output_parent):
1518 for child in self_node:
1519 self.apply_templates(context, child, output_parent)
1520
1521 extensions = { ('testns', 'myext') : MyExt() }
1522
1523 result = tree.xslt(style, extensions=extensions)
1524 self.assertEquals(etree.tostring(result),
1525 _bytes('<?test TEST?><Y>XYZ</Y><!--TEST-->'))
1526
1528 tree = self.parse('<a><b>E</b></a>')
1529 style = self.parse('''\
1530 <xsl:stylesheet version="1.0"
1531 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1532 xmlns:myns="testns"
1533 extension-element-prefixes="myns">
1534 <xsl:template match="a">
1535 <xsl:variable name="testvar">yo</xsl:variable>
1536 <A>
1537 <myns:myext>
1538 <xsl:attribute name="attr">
1539 <xsl:value-of select="$testvar" />
1540 </xsl:attribute>
1541 <B>
1542 <xsl:choose>
1543 <xsl:when test="1 = 2"><C/></xsl:when>
1544 <xsl:otherwise><D><xsl:value-of select="b/text()" /></D></xsl:otherwise>
1545 </xsl:choose>
1546 </B>
1547 </myns:myext>
1548 </A>
1549 </xsl:template>
1550 </xsl:stylesheet>''')
1551
1552 class MyExt(etree.XSLTExtension):
1553 def execute(self, context, self_node, input_node, output_parent):
1554 el = etree.Element('MY')
1555 self.process_children(context, el)
1556 output_parent.append(el)
1557
1558 extensions = { ('testns', 'myext') : MyExt() }
1559
1560 result = tree.xslt(style, extensions=extensions)
1561 self.assertEquals(self._rootstring(result),
1562 _bytes('<A><MYattr="yo"><B><D>E</D></B></MY></A>'))
1563
1565 tree = self.parse('<a/>')
1566 style = self.parse('''\
1567 <xsl:stylesheet version="1.0"
1568 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1569 xmlns:myns="testns"
1570 extension-element-prefixes="myns">
1571 <xsl:template match="a">
1572 <myns:myext>
1573 <A/>
1574 </myns:myext>
1575 </xsl:template>
1576 </xsl:stylesheet>''')
1577
1578 class MyExt(etree.XSLTExtension):
1579 def execute(self, context, self_node, input_node, output_parent):
1580 self.process_children(context, output_parent)
1581
1582 extensions = { ('testns', 'myext') : MyExt() }
1583
1584 result = tree.xslt(style, extensions=extensions)
1585 self.assertEquals(self._rootstring(result),
1586 _bytes('<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, self_node)
1605
1606 extensions = { ('testns', 'myext') : MyExt() }
1607
1608 self.assertRaises(TypeError, tree.xslt, style, extensions=extensions)
1609
1611 tree = self.parse('<a/>')
1612 style = self.parse('''\
1613 <xsl:stylesheet version="1.0"
1614 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1615 xmlns:myns="testns"
1616 extension-element-prefixes="myns">
1617 <xsl:template match="a">
1618 <myns:myext>
1619 <A><myns:myext><B/></myns:myext></A>
1620 </myns:myext>
1621 </xsl:template>
1622 </xsl:stylesheet>''')
1623
1624 class MyExt(etree.XSLTExtension):
1625 callback_call_counter = 0
1626 def execute(self, context, self_node, input_node, output_parent):
1627 self.callback_call_counter += 1
1628 el = etree.Element('MY', n=str(self.callback_call_counter))
1629 self.process_children(context, el)
1630 output_parent.append(el)
1631
1632 extensions = { ('testns', 'myext') : MyExt() }
1633
1634 result = tree.xslt(style, extensions=extensions)
1635 self.assertEquals(self._rootstring(result),
1636 _bytes('<MYn="1"><A><MYn="2"><B/></MY></A></MY>'))
1637
1639 tree = self.parse('<a><b>B</b></a>')
1640 style = self.parse('''\
1641 <xsl:stylesheet version="1.0"
1642 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1643 xmlns:myns="testns"
1644 extension-element-prefixes="myns"
1645 exclude-result-prefixes="myns">
1646 <xsl:template match="a">
1647 <A><myns:myext>b</myns:myext></A>
1648 </xsl:template>
1649 </xsl:stylesheet>''')
1650
1651 class MyError(Exception):
1652 pass
1653
1654 class MyExt(etree.XSLTExtension):
1655 def execute(self, context, self_node, input_node, output_parent):
1656 raise MyError("expected!")
1657
1658 extensions = { ('testns', 'myext') : MyExt() }
1659 self.assertRaises(MyError, tree.xslt, style, extensions=extensions)
1660
1661
1663 """XSLT tests for etree under Python 3"""
1665 tree = self.parse('<a><b>B</b><c>C</c></a>')
1666 style = self.parse('''\
1667 <xsl:stylesheet version="1.0"
1668 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1669 <xsl:template match="*" />
1670 <xsl:template match="/">
1671 <foo><xsl:value-of select="/a/b/text()" /></foo>
1672 </xsl:template>
1673 </xsl:stylesheet>''')
1674
1675 st = etree.XSLT(style)
1676 res = st(tree)
1677 self.assertEquals(_bytes('''\
1678 <?xml version="1.0"?>
1679 <foo>B</foo>
1680 '''),
1681 bytes(res))
1682
1684 tree = self.parse('<a><b>B</b><c>C</c></a>')
1685 style = self.parse('''\
1686 <xsl:stylesheet version="1.0"
1687 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1688 <xsl:template match="*" />
1689 <xsl:template match="/">
1690 <foo><xsl:value-of select="/a/b/text()" /></foo>
1691 </xsl:template>
1692 </xsl:stylesheet>''')
1693
1694 st = etree.XSLT(style)
1695 res = st(tree)
1696 self.assertEquals(_bytes('''\
1697 <?xml version="1.0"?>
1698 <foo>B</foo>
1699 '''),
1700 bytearray(res))
1701
1703 tree = self.parse('<a><b>B</b><c>C</c></a>')
1704 style = self.parse('''\
1705 <xsl:stylesheet version="1.0"
1706 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1707 <xsl:template match="*" />
1708 <xsl:template match="/">
1709 <foo><xsl:value-of select="/a/b/text()" /></foo>
1710 </xsl:template>
1711 </xsl:stylesheet>''')
1712
1713 st = etree.XSLT(style)
1714 res = st(tree)
1715 self.assertEquals(_bytes('''\
1716 <?xml version="1.0"?>
1717 <foo>B</foo>
1718 '''),
1719 bytes(memoryview(res)))
1720
1721
1734
1735 if __name__ == '__main__':
1736 print('to test use test.py %s' % __file__)
1737