1 from constants
import XSLT_NS
2 from xml
.dom
import Node
4 from Ft
.Xml
.Xslt
.StylesheetReader
import StylesheetReader
5 from Ft
.Xml
.Xslt
.StylesheetTree
import XsltElement
, XsltText
6 from Ft
.Xml
.Xslt
.LiteralElement
import LiteralElement
7 from Ft
.Xml
.Xslt
.ApplyTemplatesElement
import ApplyTemplatesElement
8 from Program
import Program
, Op
, Block
10 def import_sheet(doc
):
13 root
= Program('XSLT')
15 # The root program puts the mark on the Result node and the cursor on the Source.
16 # It then runs the program for the default mode. There is one program for each mode, and
17 # it acts as a dispatcher. It finds a template which matches the cursor node and runs
18 # the program for that template.
20 op
= add(root
.code
.start
, 'do_search', '/xslt/Result')
21 op
= add(op
, 'mark_selection')
22 op
= add(op
, 'do_search', '/xslt/Source')
23 op
= add(op
, 'play', 'XSLT/Default mode')
25 # This program copies a text node to the output
26 prog
= Program('DefaultText')
28 op
= add(prog
.code
.start
, 'yank')
29 op
= add(op
, 'mark_switch')
30 op
= add(op
, 'put_as_child_end')
31 op
= add(op
, 'move_left')
32 op
= add(op
, 'mark_switch')
34 # To start with, the cursor is on the source document node and
35 # the mark is on the result document node.
37 # The mode program is called with:
38 # => Cursor = context node
39 # Mark = result parent (append children here)
40 # <= Cursor is undefined
43 reader
= StylesheetReader()
44 sheet
= reader
.fromDocument(doc
)
50 # sheet.matchTemplates is { mode -> { type -> { (ns, name) -> [match] for elements
53 # Each match is (pattern, axis_type, TemplateElement)
55 # The list of matches is sorted; use the first that matches. Multiple lookups
56 # may be required (eg, lookup 'html' then None (for 'node()' and '*')).
57 # Patterns like 'text()|comment()' are broken down into two match elements.
59 # XXX: Could have two modes with the same name but different namespaces...
63 for mode
in sheet
.matchTemplates
.keys():
65 mode_name
= 'Mode:' + mode
[1]
67 mode_name
= 'Default mode'
68 prog
= Program(mode_name
)
70 tests
= prog
.code
.start
72 types
= sheet
.matchTemplates
[mode
]
74 for type in types
.keys():
75 if type == Node
.ELEMENT_NODE
:
76 templates
= types
[type].values()
78 templates
= [types
[type]]
82 name
= pattern
.replace('/', '%')
83 temp
= Program(`i`
+ '-' + name
)
84 op
= add(temp
.code
.start
, 'mark_switch')
85 make_template(op
, t
[2])
89 if pattern
.startswith('/'):
92 pattern
= '/xslt/Source' + pattern
# XXX: Hack
93 tests
= add(tests
, 'fail_if', pattern
)
94 op
= Op(action
= ['play', temp
.get_path()])
95 tests
.link_to(op
, 'fail')
97 # Now add the built-in rules
99 print "Tidy", loose_ends
101 tests
= add(tests
, 'fail_if', 'text()')
102 op
= Op(action
= ['play', 'XSLT/DefaultText'])
103 tests
.link_to(op
, 'fail')
105 tests
= add(tests
, 'do_global', '*')
106 tests
= add(tests
, 'map', prog
.get_path())
107 tests
= add(tests
, 'mark_switch')
108 tests
= add(tests
, 'mark_switch')
109 [ op
.link_to(tests
, 'next') for op
in loose_ends
]
114 def add(op
, *action
):
115 new
= Op(action
= action
)
116 op
.link_to(new
, 'next')
119 # A template is instantiated by running its program.
121 # => Cursor = result parent (append here)
122 # Mark = context node
124 # <= Cursor is undefined
127 # Add the instructions to instantiate this template to 'op'.
128 def make_template(op
, temp
):
129 for child
in temp
.children
:
130 if isinstance(child
, XsltText
):
131 print "Text node", child
.data
132 op
= add(op
, 'add_node', 'et', child
.data
)
133 op
= add(op
, 'move_left')
135 elif isinstance(child
, LiteralElement
):
136 print "Element", child
._output
_qname
137 op
= add(op
, 'add_node', 'ee', child
._output
_qname
)
138 op
= make_template(op
, child
)
139 op
= add(op
, 'move_left')
140 elif isinstance(child
, ApplyTemplatesElement
):
141 block
= Block(op
.parent
)
142 block
.toggle_restore()
146 match
= `child
._select`
150 print "MATCH:", match
151 sub
= add(sub
, 'mark_switch')
152 sub
= add(sub
, 'do_global', match
)
153 sub
= add(sub
, 'map', 'XSLT/Default mode')
154 sub
= add(sub
, 'mark_switch')
156 op
.link_to(block
, 'next')
159 print "Unknown template type", child
, "(%s)" % child
.__class
__