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
793
795 root = etree.XML(_bytes('''\
796 <transform>
797 <widget displayType="fieldset"/>
798 </transform>'''))
799
800 xslt = etree.XSLT(etree.XML(_bytes('''\
801 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
802 <xsl:output method="html" indent="no"/>
803 <xsl:template match="/">
804 <html>
805 <xsl:apply-templates/>
806 </html>
807 </xsl:template>
808
809 <xsl:template match="widget">
810 <xsl:element name="{@displayType}"/>
811 </xsl:template>
812
813 </xsl:stylesheet>''')))
814
815 result = xslt(root[0])
816 root[:] = result.getroot()[:]
817 del root
818
820 tree = self.parse('''\
821 <?xml version="1.0"?>
822 <?xml-stylesheet type="text/xsl" href="%s"?>
823 <a>
824 <b>B</b>
825 <c>C</c>
826 </a>''' % fileInTestDir("test1.xslt"))
827
828 style_root = tree.getroot().getprevious().parseXSL().getroot()
829 self.assertEqual("{http://www.w3.org/1999/XSL/Transform}stylesheet",
830 style_root.tag)
831
833
834 tree = self.parse('''\
835 <?xml version="1.0"?>
836 <?xml-stylesheet type="text/xsl" href="#style"?>
837 <a>
838 <b>B</b>
839 <c>C</c>
840 <xsl:stylesheet version="1.0" xml:id="style"
841 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
842 <xsl:template match="*" />
843 <xsl:template match="/">
844 <foo><xsl:value-of select="/a/b/text()" /></foo>
845 </xsl:template>
846 </xsl:stylesheet>
847 </a>''')
848
849 style_root = tree.getroot().getprevious().parseXSL().getroot()
850 self.assertEqual("{http://www.w3.org/1999/XSL/Transform}stylesheet",
851 style_root.tag)
852
853 st = etree.XSLT(style_root)
854 res = st(tree)
855 self.assertEqual('''\
856 <?xml version="1.0"?>
857 <foo>B</foo>
858 ''',
859 str(res))
860
862
863 tree = self.parse('''\
864 <?xml version="1.0"?>
865 <?xml-stylesheet type="text/xsl" href="#style"?>
866 <a>
867 <b>B</b>
868 <c>C</c>
869 </a>''')
870
871 style = self.parse('''\
872 <xsl:stylesheet version="1.0" xml:id="style"
873 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
874 <xsl:template match="*" />
875 <xsl:template match="/">
876 <foo><xsl:value-of select="/a/b/text()" /></foo>
877 </xsl:template>
878 </xsl:stylesheet>
879 ''')
880
881 tree.getroot().append(style.getroot())
882
883 style_root = tree.getroot().getprevious().parseXSL().getroot()
884 self.assertEqual("{http://www.w3.org/1999/XSL/Transform}stylesheet",
885 style_root.tag)
886
887 st = etree.XSLT(style_root)
888 res = st(tree)
889 self.assertEqual('''\
890 <?xml version="1.0"?>
891 <foo>B</foo>
892 ''',
893 str(res))
894
896 tree = self.parse('''\
897 <?xml version="1.0"?>
898 <?xml-stylesheet type="text/xsl" href="TEST"?>
899 <a>
900 <b>B</b>
901 <c>C</c>
902 </a>''')
903
904 pi = tree.getroot().getprevious()
905 self.assertEqual("TEST", pi.get("href"))
906
908 tree = self.parse('''\
909 <?xml version="1.0"?>
910 <?xml-stylesheet type="text/xsl" href="TEST"?>
911 <a>
912 <b>B</b>
913 <c>C</c>
914 </a>''')
915
916 pi = tree.getroot().getprevious()
917 self.assertEqual("TEST", pi.get("href"))
918 self.assertEqual("text/xsl", pi.get("type"))
919 self.assertEqual(None, pi.get("motz"))
920
922 tree = self.parse('''\
923 <?xml version="1.0"?>
924 <?xml-stylesheet href="TEST" type="text/xsl"?>
925 <a>
926 <b>B</b>
927 <c>C</c>
928 </a>''')
929
930 pi = tree.getroot().getprevious()
931 self.assertEqual("TEST", pi.get("href"))
932 self.assertEqual("text/xsl", pi.get("type"))
933 self.assertEqual(None, pi.get("motz"))
934
936 tree = self.parse('''\
937 <?xml version="1.0"?>
938 <?xml-stylesheet type="text/xsl" href="TEST"?>
939 <a>
940 <b>B</b>
941 <c>C</c>
942 </a>''')
943
944 pi = tree.getroot().getprevious()
945 self.assertEqual(None, pi.get("unknownattribute"))
946
948 tree = self.parse('''\
949 <?xml version="1.0"?>
950 <?xml-stylesheet type="text/xsl" href="TEST"?>
951 <a>
952 <b>B</b>
953 <c>C</c>
954 </a>''')
955
956 pi = tree.getroot().getprevious()
957 self.assertEqual("TEST", pi.get("href"))
958
959 pi.set("href", "TEST123")
960 self.assertEqual("TEST123", pi.get("href"))
961
963 tree = self.parse('''\
964 <?xml version="1.0"?>
965 <?xml-stylesheet type="text/xsl"?>
966 <a>
967 <b>B</b>
968 <c>C</c>
969 </a>''')
970
971 pi = tree.getroot().getprevious()
972 self.assertEqual(None, pi.get("href"))
973
974 pi.set("href", "TEST")
975 self.assertEqual("TEST", pi.get("href"))
976
978 """EXSLT tests"""
979
981 tree = self.parse('<a><b>B</b><c>C</c></a>')
982 style = self.parse('''\
983 <xsl:stylesheet version="1.0"
984 xmlns:str="http://exslt.org/strings"
985 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
986 exclude-result-prefixes="str xsl">
987 <xsl:template match="text()">
988 <xsl:value-of select="str:align(string(.), '***', 'center')" />
989 </xsl:template>
990 <xsl:template match="*">
991 <xsl:copy>
992 <xsl:apply-templates/>
993 </xsl:copy>
994 </xsl:template>
995 </xsl:stylesheet>''')
996
997 st = etree.XSLT(style)
998 res = st(tree)
999 self.assertEqual('''\
1000 <?xml version="1.0"?>
1001 <a><b>*B*</b><c>*C*</c></a>
1002 ''',
1003 str(res))
1004
1005 if etree.LIBXSLT_VERSION >= (1,1,21):
1007 tree = self.parse('<a><b>B</b><c>C</c></a>')
1008 style = self.parse('''\
1009 <xsl:stylesheet version = "1.0"
1010 xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
1011 xmlns:str="http://exslt.org/strings"
1012 extension-element-prefixes="str">
1013
1014 <xsl:template match="/">
1015 <h1 class="{str:replace('abc', 'b', 'x')}">test</h1>
1016 </xsl:template>
1017
1018 </xsl:stylesheet>''')
1019
1020 st = etree.XSLT(style)
1021 res = st(tree)
1022 self.assertEqual('''\
1023 <?xml version="1.0"?>
1024 <h1 class="axc">test</h1>
1025 ''',
1026 str(res))
1027
1029 tree = self.parse('<a><b>B</b><c>C</c></a>')
1030 style = self.parse('''\
1031 <xsl:stylesheet version="1.0"
1032 xmlns:math="http://exslt.org/math"
1033 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1034 exclude-result-prefixes="math xsl">
1035 <xsl:template match="*">
1036 <xsl:copy>
1037 <xsl:attribute name="pi">
1038 <xsl:value-of select="math:constant('PI', count(*)+2)"/>
1039 </xsl:attribute>
1040 <xsl:apply-templates/>
1041 </xsl:copy>
1042 </xsl:template>
1043 </xsl:stylesheet>''')
1044
1045 st = etree.XSLT(style)
1046 res = st(tree)
1047 self.assertEqual('''\
1048 <?xml version="1.0"?>
1049 <a pi="3.14"><b pi="3">B</b><c pi="3">C</c></a>
1050 ''',
1051 str(res))
1052
1054 xslt = etree.XSLT(etree.XML(_bytes("""\
1055 <xsl:stylesheet version="1.0"
1056 xmlns:regexp="http://exslt.org/regular-expressions"
1057 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1058 <xsl:template match="*">
1059 <test><xsl:copy-of select="*[regexp:test(string(.), '8.')]"/></test>
1060 </xsl:template>
1061 </xsl:stylesheet>
1062 """)))
1063 result = xslt(etree.XML(_bytes('<a><b>123</b><b>098</b><b>987</b></a>')))
1064 root = result.getroot()
1065 self.assertEqual(root.tag,
1066 'test')
1067 self.assertEqual(len(root), 1)
1068 self.assertEqual(root[0].tag,
1069 'b')
1070 self.assertEqual(root[0].text,
1071 '987')
1072
1074 xslt = etree.XSLT(etree.XML("""\
1075 <xsl:stylesheet version="1.0"
1076 xmlns:regexp="http://exslt.org/regular-expressions"
1077 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1078 <xsl:template match="*">
1079 <test>
1080 <xsl:copy-of select="regexp:replace(string(.), 'd.', '', 'XX')"/>
1081 <xsl:text>-</xsl:text>
1082 <xsl:copy-of select="regexp:replace(string(.), 'd.', 'gi', 'XX')"/>
1083 </test>
1084 </xsl:template>
1085 </xsl:stylesheet>
1086 """))
1087 result = xslt(etree.XML(_bytes('<a>abdCdEeDed</a>')))
1088 root = result.getroot()
1089 self.assertEqual(root.tag,
1090 'test')
1091 self.assertEqual(len(root), 0)
1092 self.assertEqual(root.text, 'abXXdEeDed-abXXXXeXXd')
1093
1095 xslt = etree.XSLT(etree.XML("""\
1096 <xsl:stylesheet version="1.0"
1097 xmlns:regexp="http://exslt.org/regular-expressions"
1098 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1099 <xsl:template match="*">
1100 <test>
1101 <test1><xsl:copy-of select="regexp:match(string(.), 'd.')"/></test1>
1102 <test2><xsl:copy-of select="regexp:match(string(.), 'd.', 'g')"/></test2>
1103 <test2i><xsl:copy-of select="regexp:match(string(.), 'd.', 'gi')"/></test2i>
1104 </test>
1105 </xsl:template>
1106 </xsl:stylesheet>
1107 """))
1108 result = xslt(etree.XML(_bytes('<a>abdCdEeDed</a>')))
1109 root = result.getroot()
1110 self.assertEqual(root.tag, 'test')
1111 self.assertEqual(len(root), 3)
1112
1113 self.assertEqual(len(root[0]), 1)
1114 self.assertEqual(root[0][0].tag, 'match')
1115 self.assertEqual(root[0][0].text, 'dC')
1116
1117 self.assertEqual(len(root[1]), 2)
1118 self.assertEqual(root[1][0].tag, 'match')
1119 self.assertEqual(root[1][0].text, 'dC')
1120 self.assertEqual(root[1][1].tag, 'match')
1121 self.assertEqual(root[1][1].text, 'dE')
1122
1123 self.assertEqual(len(root[2]), 3)
1124 self.assertEqual(root[2][0].tag, 'match')
1125 self.assertEqual(root[2][0].text, 'dC')
1126 self.assertEqual(root[2][1].tag, 'match')
1127 self.assertEqual(root[2][1].text, 'dE')
1128 self.assertEqual(root[2][2].tag, 'match')
1129 self.assertEqual(root[2][2].text, 'De')
1130
1132 xslt = etree.XSLT(etree.XML(_bytes("""\
1133 <xsl:stylesheet version="1.0"
1134 xmlns:regexp="http://exslt.org/regular-expressions"
1135 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1136 <xsl:template match="/">
1137 <test>
1138 <xsl:for-each select="regexp:match(
1139 '123abc567', '([0-9]+)([a-z]+)([0-9]+)' )">
1140 <test1><xsl:value-of select="."/></test1>
1141 </xsl:for-each>
1142 </test>
1143 </xsl:template>
1144 </xsl:stylesheet>
1145 """)))
1146 result = xslt(etree.XML(_bytes('<a/>')))
1147 root = result.getroot()
1148 self.assertEqual(root.tag, 'test')
1149 self.assertEqual(len(root), 4)
1150
1151 self.assertEqual(root[0].text, "123abc567")
1152 self.assertEqual(root[1].text, "123")
1153 self.assertEqual(root[2].text, "abc")
1154 self.assertEqual(root[3].text, "567")
1155
1157
1158 xslt = etree.XSLT(etree.XML(_bytes("""\
1159 <xsl:stylesheet version="1.0"
1160 xmlns:regexp="http://exslt.org/regular-expressions"
1161 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1162 <xsl:template match="/">
1163 <test>
1164 <xsl:for-each select="regexp:match(
1165 'http://www.bayes.co.uk/xml/index.xml?/xml/utils/rechecker.xml',
1166 '(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)')">
1167 <test1><xsl:value-of select="."/></test1>
1168 </xsl:for-each>
1169 </test>
1170 </xsl:template>
1171 </xsl:stylesheet>
1172 """)))
1173 result = xslt(etree.XML(_bytes('<a/>')))
1174 root = result.getroot()
1175 self.assertEqual(root.tag, 'test')
1176 self.assertEqual(len(root), 5)
1177
1178 self.assertEqual(
1179 root[0].text,
1180 "http://www.bayes.co.uk/xml/index.xml?/xml/utils/rechecker.xml")
1181 self.assertEqual(
1182 root[1].text,
1183 "http")
1184 self.assertEqual(
1185 root[2].text,
1186 "www.bayes.co.uk")
1187 self.assertFalse(root[3].text)
1188 self.assertEqual(
1189 root[4].text,
1190 "/xml/index.xml?/xml/utils/rechecker.xml")
1191
1193
1194 xslt = etree.XSLT(self.parse("""\
1195 <xsl:stylesheet version="1.0"
1196 xmlns:regexp="http://exslt.org/regular-expressions"
1197 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1198 <xsl:template match="/">
1199 <test>
1200 <xsl:for-each select="regexp:match(
1201 'This is a test string', '(\w+)', 'g')">
1202 <test1><xsl:value-of select="."/></test1>
1203 </xsl:for-each>
1204 </test>
1205 </xsl:template>
1206 </xsl:stylesheet>
1207 """))
1208 result = xslt(etree.XML(_bytes('<a/>')))
1209 root = result.getroot()
1210 self.assertEqual(root.tag, 'test')
1211 self.assertEqual(len(root), 5)
1212
1213 self.assertEqual(root[0].text, "This")
1214 self.assertEqual(root[1].text, "is")
1215 self.assertEqual(root[2].text, "a")
1216 self.assertEqual(root[3].text, "test")
1217 self.assertEqual(root[4].text, "string")
1218
1220
1221
1222 xslt = etree.XSLT(etree.XML(_bytes("""\
1223 <xsl:stylesheet version="1.0"
1224 xmlns:regexp="http://exslt.org/regular-expressions"
1225 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1226 <xsl:template match="/">
1227 <test>
1228 <xsl:for-each select="regexp:match(
1229 'This is a test string', '([a-z])+ ', 'g')">
1230 <test1><xsl:value-of select="."/></test1>
1231 </xsl:for-each>
1232 </test>
1233 </xsl:template>
1234 </xsl:stylesheet>
1235 """)))
1236 result = xslt(etree.XML(_bytes('<a/>')))
1237 root = result.getroot()
1238 self.assertEqual(root.tag, 'test')
1239 self.assertEqual(len(root), 4)
1240
1241 self.assertEqual(root[0].text, "his")
1242 self.assertEqual(root[1].text, "is")
1243 self.assertEqual(root[2].text, "a")
1244 self.assertEqual(root[3].text, "test")
1245
1247
1248
1249 xslt = etree.XSLT(etree.XML(_bytes("""\
1250 <xsl:stylesheet version="1.0"
1251 xmlns:regexp="http://exslt.org/regular-expressions"
1252 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1253 <xsl:template match="/">
1254 <test>
1255 <xsl:for-each select="regexp:match(
1256 'This is a test string', '([a-z])+ ', 'gi')">
1257 <test1><xsl:value-of select="."/></test1>
1258 </xsl:for-each>
1259 </test>
1260 </xsl:template>
1261 </xsl:stylesheet>
1262 """)))
1263 result = xslt(etree.XML(_bytes('<a/>')))
1264 root = result.getroot()
1265 self.assertEqual(root.tag, 'test')
1266 self.assertEqual(len(root), 4)
1267
1268 self.assertEqual(root[0].text, "This")
1269 self.assertEqual(root[1].text, "is")
1270 self.assertEqual(root[2].text, "a")
1271 self.assertEqual(root[3].text, "test")
1272
1273
1274 -class ETreeXSLTExtFuncTestCase(HelperTestCase):
1275 """Tests for XPath extension functions in XSLT."""
1276
1277 - def test_extensions1(self):
1278 tree = self.parse('<a><b>B</b></a>')
1279 style = self.parse('''\
1280 <xsl:stylesheet version="1.0"
1281 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1282 xmlns:myns="testns"
1283 exclude-result-prefixes="myns">
1284 <xsl:template match="a"><A><xsl:value-of select="myns:mytext(b)"/></A></xsl:template>
1285 </xsl:stylesheet>''')
1286
1287 def mytext(ctxt, values):
1288 return 'X' * len(values)
1289
1290 result = tree.xslt(style, {('testns', 'mytext') : mytext})
1291 self.assertEqual(self._rootstring(result),
1292 _bytes('<A>X</A>'))
1293
1294 - def test_extensions2(self):
1295 tree = self.parse('<a><b>B</b></a>')
1296 style = self.parse('''\
1297 <xsl:stylesheet version="1.0"
1298 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1299 xmlns:myns="testns"
1300 exclude-result-prefixes="myns">
1301 <xsl:template match="a"><A><xsl:value-of select="myns:mytext(b)"/></A></xsl:template>
1302 </xsl:stylesheet>''')
1303
1304 def mytext(ctxt, values):
1305 return 'X' * len(values)
1306
1307 namespace = etree.FunctionNamespace('testns')
1308 namespace['mytext'] = mytext
1309
1310 result = tree.xslt(style)
1311 self.assertEqual(self._rootstring(result),
1312 _bytes('<A>X</A>'))
1313
1315 tree = self.parse('<a><b>B</b><b/></a>')
1316 style = self.parse('''\
1317 <xsl:stylesheet version="1.0"
1318 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1319 xmlns:myns="testns"
1320 exclude-result-prefixes="myns">
1321 <xsl:template match="a">
1322 <xsl:variable name="content">
1323 <xsl:apply-templates/>
1324 </xsl:variable>
1325 <A><xsl:value-of select="myns:mytext($content)"/></A>
1326 </xsl:template>
1327 <xsl:template match="b"><xsl:copy>BBB</xsl:copy></xsl:template>
1328 </xsl:stylesheet>''')
1329
1330 def mytext(ctxt, values):
1331 for value in values:
1332 self.assertTrue(hasattr(value, 'tag'),
1333 "%s is not an Element" % type(value))
1334 self.assertEqual(value.tag, 'b')
1335 self.assertEqual(value.text, 'BBB')
1336 return 'X'.join([el.tag for el in values])
1337
1338 namespace = etree.FunctionNamespace('testns')
1339 namespace['mytext'] = mytext
1340
1341 result = tree.xslt(style)
1342 self.assertEqual(self._rootstring(result),
1343 _bytes('<A>bXb</A>'))
1344
1345
1346 -class ETreeXSLTExtElementTestCase(HelperTestCase):
1347 """Tests for extension elements in XSLT."""
1348
1350 tree = self.parse('<a><b>B</b></a>')
1351 style = self.parse('''\
1352 <xsl:stylesheet version="1.0"
1353 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1354 xmlns:myns="testns"
1355 extension-element-prefixes="myns"
1356 exclude-result-prefixes="myns">
1357 <xsl:template match="a">
1358 <A><myns:myext>b</myns:myext></A>
1359 </xsl:template>
1360 </xsl:stylesheet>''')
1361
1362 class MyExt(etree.XSLTExtension):
1363 def execute(self, context, self_node, input_node, output_parent):
1364 child = etree.Element(self_node.text)
1365 child.text = 'X'
1366 output_parent.append(child)
1367
1368 extensions = { ('testns', 'myext') : MyExt() }
1369
1370 result = tree.xslt(style, extensions=extensions)
1371 self.assertEqual(self._rootstring(result),
1372 _bytes('<A><b>X</b></A>'))
1373
1375 tree = self.parse('<a><b>B</b></a>')
1376 style = self.parse('''\
1377 <xsl:stylesheet version="1.0"
1378 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1379 xmlns:myns="testns"
1380 extension-element-prefixes="myns"
1381 exclude-result-prefixes="myns">
1382 <xsl:template match="/">
1383 <A><myns:myext>b</myns:myext></A>
1384 </xsl:template>
1385 </xsl:stylesheet>''')
1386
1387 tags = []
1388
1389 class MyExt(etree.XSLTExtension):
1390 def execute(self, context, self_node, input_node, output_parent):
1391 tags.append(input_node.tag)
1392
1393 extensions = { ('testns', 'myext') : MyExt() }
1394
1395 result = tree.xslt(style, extensions=extensions)
1396 self.assertEqual(tags, ['a'])
1397
1399 tree = self.parse('<?test toast?><a><!--a comment--><?another pi?></a>')
1400 style = self.parse('''\
1401 <xsl:stylesheet version="1.0"
1402 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1403 xmlns:myns="testns"
1404 extension-element-prefixes="myns"
1405 exclude-result-prefixes="myns">
1406 <xsl:template match="/">
1407 <ROOT><xsl:apply-templates /></ROOT>
1408 </xsl:template>
1409 <xsl:template match="comment()">
1410 <A><myns:myext>b</myns:myext></A>
1411 </xsl:template>
1412 <xsl:template match="processing-instruction()">
1413 <A><myns:myext>b</myns:myext></A>
1414 </xsl:template>
1415 </xsl:stylesheet>''')
1416
1417 text = []
1418
1419 class MyExt(etree.XSLTExtension):
1420 def execute(self, context, self_node, input_node, output_parent):
1421 text.append(input_node.text)
1422
1423 extensions = { ('testns', 'myext') : MyExt() }
1424
1425 result = tree.xslt(style, extensions=extensions)
1426 self.assertEqual(text, ['toast', 'a comment', 'pi'])
1427
1429
1430 tree = self.parse('<a test="A"><b attr="B"/></a>')
1431 style = self.parse('''\
1432 <xsl:stylesheet version="1.0"
1433 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1434 xmlns:myns="testns"
1435 extension-element-prefixes="myns"
1436 exclude-result-prefixes="myns">
1437 <xsl:template match="@test">
1438 <A><myns:myext>b</myns:myext></A>
1439 </xsl:template>
1440 <xsl:template match="@attr">
1441 <A><myns:myext>b</myns:myext></A>
1442 </xsl:template>
1443 </xsl:stylesheet>''')
1444
1445 text = []
1446
1447 class MyExt(etree.XSLTExtension):
1448 def execute(self, context, self_node, attr_value, output_parent):
1449 text.append(attr_value)
1450
1451 extensions = { ('testns', 'myext') : MyExt() }
1452
1453 result = tree.xslt(style, extensions=extensions)
1454 self.assertEqual(text, ['A', 'B'])
1455
1457 tree = self.parse('<a><b>B</b></a>')
1458 style = self.parse('''\
1459 <xsl:stylesheet version="1.0"
1460 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1461 xmlns:myns="testns"
1462 extension-element-prefixes="myns">
1463 <xsl:template match="a">
1464 <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
1465 </xsl:template>
1466 </xsl:stylesheet>''')
1467
1468 class MyExt(etree.XSLTExtension):
1469 def execute(self, context, self_node, input_node, output_parent):
1470 output_parent.extend(list(self_node)[1:])
1471
1472 extensions = { ('testns', 'myext') : MyExt() }
1473
1474 result = tree.xslt(style, extensions=extensions)
1475 self.assertEqual(self._rootstring(result),
1476 _bytes('<A><y>Y</y><z/></A>'))
1477
1479 tree = self.parse('<a><b>B</b></a>')
1480 style = self.parse('''\
1481 <xsl:stylesheet version="1.0"
1482 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1483 xmlns:myns="testns"
1484 extension-element-prefixes="myns">
1485 <xsl:template match="a">
1486 <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
1487 </xsl:template>
1488 <xsl:template match="x" />
1489 <xsl:template match="z">XYZ</xsl:template>
1490 </xsl:stylesheet>''')
1491
1492 class MyExt(etree.XSLTExtension):
1493 def execute(self, context, self_node, input_node, output_parent):
1494 for child in self_node:
1495 for result in self.apply_templates(context, child):
1496 if isinstance(result, basestring):
1497 el = etree.Element("T")
1498 el.text = result
1499 else:
1500 el = result
1501 output_parent.append(el)
1502
1503 extensions = { ('testns', 'myext') : MyExt() }
1504
1505 result = tree.xslt(style, extensions=extensions)
1506 self.assertEqual(self._rootstring(result),
1507 _bytes('<A><T>Y</T><T>XYZ</T></A>'))
1508
1510 tree = self.parse('<a><b>B</b></a>')
1511 style = self.parse('''\
1512 <xsl:stylesheet version="1.0"
1513 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1514 xmlns:myns="testns"
1515 extension-element-prefixes="myns">
1516 <xsl:template match="a">
1517 <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
1518 </xsl:template>
1519 <xsl:template match="x"><X/></xsl:template>
1520 <xsl:template match="z">XYZ</xsl:template>
1521 </xsl:stylesheet>''')
1522
1523 class MyExt(etree.XSLTExtension):
1524 def execute(self, context, self_node, input_node, output_parent):
1525 for child in self_node:
1526 for result in self.apply_templates(context, child,
1527 elements_only=True):
1528 assert not isinstance(result, basestring)
1529 output_parent.append(result)
1530
1531 extensions = { ('testns', 'myext') : MyExt() }
1532
1533 result = tree.xslt(style, extensions=extensions)
1534 self.assertEqual(self._rootstring(result),
1535 _bytes('<A><X/></A>'))
1536
1538 tree = self.parse('<a><b>B</b></a>')
1539 style = self.parse('''\
1540 <xsl:stylesheet version="1.0"
1541 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1542 xmlns:myns="testns"
1543 extension-element-prefixes="myns">
1544 <xsl:template match="a">
1545 <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
1546 </xsl:template>
1547 <xsl:template match="x"><X/></xsl:template>
1548 <xsl:template match="y"><xsl:text> </xsl:text></xsl:template>
1549 <xsl:template match="z">XYZ</xsl:template>
1550 </xsl:stylesheet>''')
1551
1552 class MyExt(etree.XSLTExtension):
1553 def execute(self, context, self_node, input_node, output_parent):
1554 for child in self_node:
1555 for result in self.apply_templates(context, child,
1556 remove_blank_text=True):
1557 if isinstance(result, basestring):
1558 assert result.strip()
1559 el = etree.Element("T")
1560 el.text = result
1561 else:
1562 el = result
1563 output_parent.append(el)
1564
1565 extensions = { ('testns', 'myext') : MyExt() }
1566
1567 result = tree.xslt(style, extensions=extensions)
1568 self.assertEqual(self._rootstring(result),
1569 _bytes('<A><X/><T>XYZ</T></A>'))
1570
1572 tree = self.parse('<a><b>B</b></a>')
1573 style = self.parse('''\
1574 <xsl:stylesheet version="1.0"
1575 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1576 xmlns:myns="testns"
1577 extension-element-prefixes="myns">
1578 <xsl:template match="a">
1579 <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
1580 </xsl:template>
1581 <xsl:template match="x" />
1582 <xsl:template match="z">XYZ</xsl:template>
1583 </xsl:stylesheet>''')
1584
1585 class MyExt(etree.XSLTExtension):
1586 def execute(self, context, self_node, input_node, output_parent):
1587 for child in self_node:
1588 self.apply_templates(context, child, output_parent)
1589
1590 extensions = { ('testns', 'myext') : MyExt() }
1591
1592 result = tree.xslt(style, extensions=extensions)
1593 self.assertEqual(self._rootstring(result),
1594 _bytes('<A>YXYZ</A>'))
1595
1597 tree = self.parse('<a><b>B</b></a>')
1598 style = self.parse('''\
1599 <xsl:stylesheet version="1.0"
1600 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1601 xmlns:myns="testns"
1602 extension-element-prefixes="myns">
1603 <xsl:template match="a">
1604 <myns:myext><x>X</x><y>Y</y><z/></myns:myext>
1605 </xsl:template>
1606 <xsl:template match="x"><xsl:processing-instruction name="test">TEST</xsl:processing-instruction></xsl:template>
1607 <xsl:template match="y"><Y>XYZ</Y></xsl:template>
1608 <xsl:template match="z"><xsl:comment>TEST</xsl:comment></xsl:template>
1609 </xsl:stylesheet>''')
1610
1611 class MyExt(etree.XSLTExtension):
1612 def execute(self, context, self_node, input_node, output_parent):
1613 for child in self_node:
1614 self.apply_templates(context, child, output_parent)
1615
1616 extensions = { ('testns', 'myext') : MyExt() }
1617
1618 result = tree.xslt(style, extensions=extensions)
1619 self.assertEqual(etree.tostring(result),
1620 _bytes('<?test TEST?><Y>XYZ</Y><!--TEST-->'))
1621
1623 tree = self.parse('<a><b>E</b></a>')
1624 style = self.parse('''\
1625 <xsl:stylesheet version="1.0"
1626 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1627 xmlns:myns="testns"
1628 extension-element-prefixes="myns">
1629 <xsl:template match="a">
1630 <xsl:variable name="testvar">yo</xsl:variable>
1631 <A>
1632 <myns:myext>
1633 <xsl:attribute name="attr">
1634 <xsl:value-of select="$testvar" />
1635 </xsl:attribute>
1636 <B>
1637 <xsl:choose>
1638 <xsl:when test="1 = 2"><C/></xsl:when>
1639 <xsl:otherwise><D><xsl:value-of select="b/text()" /></D></xsl:otherwise>
1640 </xsl:choose>
1641 </B>
1642 </myns:myext>
1643 </A>
1644 </xsl:template>
1645 </xsl:stylesheet>''')
1646
1647 class MyExt(etree.XSLTExtension):
1648 def execute(self, context, self_node, input_node, output_parent):
1649 el = etree.Element('MY')
1650 self.process_children(context, el)
1651 output_parent.append(el)
1652
1653 extensions = { ('testns', 'myext') : MyExt() }
1654
1655 result = tree.xslt(style, extensions=extensions)
1656 self.assertEqual(self._rootstring(result),
1657 _bytes('<A><MYattr="yo"><B><D>E</D></B></MY></A>'))
1658
1660 tree = self.parse('<a/>')
1661 style = self.parse('''\
1662 <xsl:stylesheet version="1.0"
1663 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1664 xmlns:myns="testns"
1665 extension-element-prefixes="myns">
1666 <xsl:template match="a">
1667 <myns:myext>
1668 <A/>
1669 </myns:myext>
1670 </xsl:template>
1671 </xsl:stylesheet>''')
1672
1673 class MyExt(etree.XSLTExtension):
1674 def execute(self, context, self_node, input_node, output_parent):
1675 self.process_children(context, output_parent)
1676
1677 extensions = { ('testns', 'myext') : MyExt() }
1678
1679 result = tree.xslt(style, extensions=extensions)
1680 self.assertEqual(self._rootstring(result),
1681 _bytes('<A/>'))
1682
1684 tree = self.parse('<a/>')
1685 style = self.parse('''\
1686 <xsl:stylesheet version="1.0"
1687 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1688 xmlns:myns="testns"
1689 extension-element-prefixes="myns">
1690 <xsl:template match="a">
1691 <myns:myext>
1692 <A/>
1693 </myns:myext>
1694 </xsl:template>
1695 </xsl:stylesheet>''')
1696
1697 class MyExt(etree.XSLTExtension):
1698 def execute(self, context, self_node, input_node, output_parent):
1699 self.process_children(context, self_node)
1700
1701 extensions = { ('testns', 'myext') : MyExt() }
1702
1703 self.assertRaises(TypeError, tree.xslt, style, extensions=extensions)
1704
1706 tree = self.parse('<a/>')
1707 style = self.parse('''\
1708 <xsl:stylesheet version="1.0"
1709 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1710 xmlns:myns="testns"
1711 extension-element-prefixes="myns">
1712 <xsl:template match="a">
1713 <myns:myext>
1714 <A><myns:myext><B/></myns:myext></A>
1715 </myns:myext>
1716 </xsl:template>
1717 </xsl:stylesheet>''')
1718
1719 class MyExt(etree.XSLTExtension):
1720 callback_call_counter = 0
1721 def execute(self, context, self_node, input_node, output_parent):
1722 self.callback_call_counter += 1
1723 el = etree.Element('MY', n=str(self.callback_call_counter))
1724 self.process_children(context, el)
1725 output_parent.append(el)
1726
1727 extensions = { ('testns', 'myext') : MyExt() }
1728
1729 result = tree.xslt(style, extensions=extensions)
1730 self.assertEqual(self._rootstring(result),
1731 _bytes('<MYn="1"><A><MYn="2"><B/></MY></A></MY>'))
1732
1734 tree = self.parse('<a><b>B</b></a>')
1735 style = self.parse('''\
1736 <xsl:stylesheet version="1.0"
1737 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
1738 xmlns:myns="testns"
1739 extension-element-prefixes="myns"
1740 exclude-result-prefixes="myns">
1741 <xsl:template match="a">
1742 <A><myns:myext>b</myns:myext></A>
1743 </xsl:template>
1744 </xsl:stylesheet>''')
1745
1746 class MyError(Exception):
1747 pass
1748
1749 class MyExt(etree.XSLTExtension):
1750 def execute(self, context, self_node, input_node, output_parent):
1751 raise MyError("expected!")
1752
1753 extensions = { ('testns', 'myext') : MyExt() }
1754 self.assertRaises(MyError, tree.xslt, style, extensions=extensions)
1755
1756
1758 """XSLT tests for etree under Python 3"""
1759
1760 pytestmark = skipif('sys.version_info < (3,0)')
1761
1763 tree = self.parse('<a><b>B</b><c>C</c></a>')
1764 style = self.parse('''\
1765 <xsl:stylesheet version="1.0"
1766 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1767 <xsl:template match="*" />
1768 <xsl:template match="/">
1769 <foo><xsl:value-of select="/a/b/text()" /></foo>
1770 </xsl:template>
1771 </xsl:stylesheet>''')
1772
1773 st = etree.XSLT(style)
1774 res = st(tree)
1775 self.assertEqual(_bytes('''\
1776 <?xml version="1.0"?>
1777 <foo>B</foo>
1778 '''),
1779 bytes(res))
1780
1782 tree = self.parse('<a><b>B</b><c>C</c></a>')
1783 style = self.parse('''\
1784 <xsl:stylesheet version="1.0"
1785 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1786 <xsl:template match="*" />
1787 <xsl:template match="/">
1788 <foo><xsl:value-of select="/a/b/text()" /></foo>
1789 </xsl:template>
1790 </xsl:stylesheet>''')
1791
1792 st = etree.XSLT(style)
1793 res = st(tree)
1794 self.assertEqual(_bytes('''\
1795 <?xml version="1.0"?>
1796 <foo>B</foo>
1797 '''),
1798 bytearray(res))
1799
1801 tree = self.parse('<a><b>B</b><c>C</c></a>')
1802 style = self.parse('''\
1803 <xsl:stylesheet version="1.0"
1804 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1805 <xsl:template match="*" />
1806 <xsl:template match="/">
1807 <foo><xsl:value-of select="/a/b/text()" /></foo>
1808 </xsl:template>
1809 </xsl:stylesheet>''')
1810
1811 st = etree.XSLT(style)
1812 res = st(tree)
1813 self.assertEqual(_bytes('''\
1814 <?xml version="1.0"?>
1815 <foo>B</foo>
1816 '''),
1817 bytes(memoryview(res)))
1818
1819
1833
1834 if __name__ == '__main__':
1835 print('to test use test.py %s' % __file__)
1836