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