mathtype_to_mathml 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.rspec +2 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +3 -0
  6. data/Gemfile +6 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +45 -0
  9. data/Rakefile +7 -0
  10. data/lib/mathtype_to_mathml.rb +28 -0
  11. data/lib/mathtype_to_mathml/char_replacer.rb +311 -0
  12. data/lib/mathtype_to_mathml/mover.rb +151 -0
  13. data/lib/mathtype_to_mathml/version.rb +3 -0
  14. data/lib/transform.xsl +104 -0
  15. data/lib/xsl/arrow.xsl +319 -0
  16. data/lib/xsl/brace.xsl +55 -0
  17. data/lib/xsl/char.xsl +35 -0
  18. data/lib/xsl/embellishment.xsl +389 -0
  19. data/lib/xsl/matrix.xsl +116 -0
  20. data/lib/xsl/pile.xsl +54 -0
  21. data/lib/xsl/subsup.xsl +55 -0
  22. data/lib/xsl/sum.xsl +57 -0
  23. data/lib/xsl/union_intersection.xsl +104 -0
  24. data/mathtype_to_mathml.gemspec +28 -0
  25. data/spec/fixtures/expected/arrows.xml +389 -0
  26. data/spec/fixtures/expected/embellishments.xml +178 -0
  27. data/spec/fixtures/expected/equation1.xml +52 -0
  28. data/spec/fixtures/expected/equation10.xml +19 -0
  29. data/spec/fixtures/expected/equation11.xml +17 -0
  30. data/spec/fixtures/expected/equation12.xml +34 -0
  31. data/spec/fixtures/expected/equation13.xml +113 -0
  32. data/spec/fixtures/expected/equation2.xml +33 -0
  33. data/spec/fixtures/expected/equation3.xml +324 -0
  34. data/spec/fixtures/expected/equation4.xml +14 -0
  35. data/spec/fixtures/expected/equation5.xml +23 -0
  36. data/spec/fixtures/expected/equation6.xml +13 -0
  37. data/spec/fixtures/expected/equation7.xml +19 -0
  38. data/spec/fixtures/expected/equation8.xml +17 -0
  39. data/spec/fixtures/expected/equation9.xml +15 -0
  40. data/spec/fixtures/input/arrows.bin +0 -0
  41. data/spec/fixtures/input/embellishments.bin +0 -0
  42. data/spec/fixtures/input/equation1.bin +0 -0
  43. data/spec/fixtures/input/equation10.bin +0 -0
  44. data/spec/fixtures/input/equation11.bin +0 -0
  45. data/spec/fixtures/input/equation12.bin +0 -0
  46. data/spec/fixtures/input/equation13.bin +0 -0
  47. data/spec/fixtures/input/equation2.bin +0 -0
  48. data/spec/fixtures/input/equation3.bin +0 -0
  49. data/spec/fixtures/input/equation4.bin +0 -0
  50. data/spec/fixtures/input/equation5.bin +0 -0
  51. data/spec/fixtures/input/equation6.bin +0 -0
  52. data/spec/fixtures/input/equation7.bin +0 -0
  53. data/spec/fixtures/input/equation8.bin +0 -0
  54. data/spec/fixtures/input/equation9.bin +0 -0
  55. data/spec/html_output.rb +28 -0
  56. data/spec/mathtype_to_mathml_spec.rb +19 -0
  57. data/spec/spec_helper.rb +2 -0
  58. metadata +220 -0
@@ -0,0 +1,151 @@
1
+ require "nokogiri"
2
+
3
+ # We're moving elements around to avoid "scanning" for characters when
4
+ # using the /scan translator mode. The original issue is that MathType
5
+ # considers subscripts and superscripts to be stand-alone, while MathML
6
+ # considers them subscripts and superscripts of an object, and the object
7
+ # is then included in the sub/superscript element.
8
+
9
+ # MathType's translator has a scan mode, which does the following:
10
+ # 1. Scanning goes to the right for commands with the "pre" option,
11
+ # otherwise left;
12
+ # 2. If we are scanning right and the object next to the template is an
13
+ # opening "fence" character (parenthesis, bracket, brace, etc.),
14
+ # the slot is scanned for the corresponding closing fence character;
15
+ # 3. If we are scanning left and the object next to the template is an closing
16
+ # "fence" character (parenthesis, bracket, brace, etc.), the slot is scanned
17
+ # for the corresponding opening fence character;
18
+ # 4. If the fenced expression is found, it is used as #1 in the template translation.
19
+
20
+ # Additionally, Mover inverts <emb>ellishments from <char><emb></emb></char> to
21
+ # <emb><char></char></emb>.
22
+
23
+ module MathTypeToMathML
24
+ class Mover
25
+ attr_reader :mathtype
26
+ attr_accessor :last_preceding_siblings
27
+
28
+ PARENS_SELECTOR = "selector='tmPARENS' or "\
29
+ "selector='tmBRACK' or " \
30
+ "selector='tmBRACE' or " \
31
+ "selector='tmOBRACK' or " \
32
+ "selector='tmOBRACE' or " \
33
+ "selector='tmHBRACK' or " \
34
+ "selector='tmHBRACE'"
35
+
36
+ SUBSUP_SELECTOR = "selector='tmSUP' or " \
37
+ "selector='tmSUB' or " \
38
+ "selector='tmSUBSUP'"
39
+
40
+ PRE = "variation='tvSU_PRECEDES'"
41
+
42
+ OPEN_PAREN = "mt_code_value = '0x0028' or " \
43
+ "mt_code_value = '0x005B' or " \
44
+ "mt_code_value = '0x007B'"
45
+
46
+ CLOSE_PAREN = "mt_code_value = '0x0029' or " \
47
+ "mt_code_value = '0x005D' or " \
48
+ "mt_code_value = '0x007D'"
49
+
50
+ OPEN_CLOSE_PAIRS = {
51
+ "0x0028" => "0x0029", # ( )
52
+ "0x005B" => "0x005D", # [ ]
53
+ "0x007B" => "0x007D", # { }
54
+ }
55
+
56
+ def initialize(mathtype)
57
+ @mathtype = mathtype
58
+ @last_preceding_siblings = Nokogiri::XML::NodeSet.new(@mathtype)
59
+ end
60
+
61
+ def move_until_mt_code(elements, mt_code_value, parent)
62
+ elements.each do |element|
63
+ element.parent = parent
64
+ break if element.xpath("mt_code_value = '#{mt_code_value}'")
65
+ end
66
+ end
67
+
68
+ def move_paren(siblings, node)
69
+ OPEN_CLOSE_PAIRS.each do |open, close|
70
+ if siblings[0].xpath("mt_code_value = '#{open}'") # ( )
71
+ move_until_mt_code(siblings, close, node)
72
+ end
73
+ end
74
+ end
75
+
76
+ def new_preceding_siblings(el)
77
+ all_siblings = el.xpath("preceding-sibling::tmpl | preceding-sibling::char")
78
+ siblings = all_siblings - last_preceding_siblings
79
+ self.last_preceding_siblings = all_siblings
80
+ siblings
81
+ end
82
+
83
+ def new_following_siblings(el)
84
+ el.xpath("following-sibling::tmpl | following-sibling::char")
85
+ end
86
+
87
+ def move_following_subsup
88
+ mathtype.xpath("//tmpl[(#{SUBSUP_SELECTOR}) and not(#{PRE})]").each do |el|
89
+ siblings = new_preceding_siblings(el)
90
+
91
+ node = Nokogiri::XML::Node.new "slot", mathtype
92
+
93
+ if siblings.last.xpath(CLOSE_PAREN)
94
+ siblings = siblings.reverse.take_while do |sibling|
95
+ !sibling.next_element.xpath(OPEN_PAREN)
96
+ end.reverse
97
+
98
+ move_paren(siblings, node)
99
+ elsif siblings.last.xpath("self::tmpl[#{PARENS_SELECTOR}]")
100
+ siblings.last.parent = node
101
+ else
102
+ siblings.last.parent = node
103
+ end
104
+
105
+ el.at_css("slot").add_previous_sibling node
106
+ end
107
+ end
108
+
109
+ def move_preceding_subsup
110
+ mathtype.xpath("//tmpl[(#{SUBSUP_SELECTOR}) and #{PRE}]").each do |el|
111
+ siblings = new_following_siblings(el)
112
+
113
+ node = Nokogiri::XML::Node.new "slot", mathtype
114
+
115
+ if siblings.first.xpath(OPEN_PAREN)
116
+ siblings = siblings.reverse.take_while do |sibling|
117
+ !sibling.next_element.xpath(CLOSE_PAREN)
118
+ end.reverse
119
+
120
+ move_paren(siblings, node)
121
+ elsif siblings.first.xpath("self::tmpl[#{PARENS_SELECTOR}]")
122
+ siblings.first.parent = node
123
+ else
124
+ siblings.first.parent = node
125
+ end
126
+
127
+ el.at_css("slot").add_previous_sibling node
128
+ end
129
+ end
130
+
131
+ def invert_char_embell
132
+ # Invert char -> embell to embell -> char.
133
+ mathtype.xpath("//char[embell]").each do |el|
134
+ embell = el.xpath("embell").first.remove
135
+ char = el.clone
136
+ char.parent = embell
137
+ el.replace(embell)
138
+ end
139
+ end
140
+
141
+ def move
142
+ move_following_subsup
143
+ move_preceding_subsup
144
+ invert_char_embell
145
+ end
146
+ end
147
+ end
148
+
149
+
150
+
151
+
@@ -0,0 +1,3 @@
1
+ module MathTypeToMathML
2
+ VERSION = "0.0.1"
3
+ end
data/lib/transform.xsl ADDED
@@ -0,0 +1,104 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
3
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
4
+ exclude-result-prefixes="xs"
5
+ version="1.0">
6
+ <xsl:template match="/">
7
+ <xsl:apply-templates select=".//mtef" />
8
+ </xsl:template>
9
+
10
+ <xsl:template match="mtef">
11
+ <math display="block">
12
+ <xsl:apply-templates select="pile | slot"/>
13
+ </math>
14
+ </xsl:template>
15
+
16
+ <xsl:template match="tmpl[selector = 'tmFRACT']">
17
+ <mfrac>
18
+ <xsl:apply-templates select="slot[1]"/>
19
+ <xsl:apply-templates select="slot[2]"/>
20
+ </mfrac>
21
+ </xsl:template>
22
+
23
+ <xsl:template match="slot">
24
+ <mrow>
25
+ <xsl:apply-templates/>
26
+ </mrow>
27
+ </xsl:template>
28
+
29
+ <xsl:template match="tmpl[selector = 'tmROOT']">
30
+ <msqrt>
31
+ <xsl:apply-templates/>
32
+ </msqrt>
33
+ </xsl:template>
34
+
35
+ <xsl:template match="char[typeface = '2']">
36
+ <mn>
37
+ <xsl:text disable-output-escaping="yes">&amp;#</xsl:text>
38
+ <xsl:value-of select="substring(mt_code_value/text(), 2)"/>
39
+ <xsl:text>;</xsl:text>
40
+ </mn>
41
+ </xsl:template>
42
+
43
+ <xsl:template match="char[typeface = '8']">
44
+ <mn>
45
+ <xsl:text disable-output-escaping="yes">&amp;#</xsl:text>
46
+ <xsl:value-of select="substring(mt_code_value/text(), 2)"/>
47
+ <xsl:text>;</xsl:text>
48
+ </mn>
49
+ </xsl:template>
50
+
51
+ <xsl:template match="char[typeface = '3']">
52
+ <mi>
53
+ <xsl:text disable-output-escaping="yes">&amp;#</xsl:text>
54
+ <xsl:value-of select="substring(mt_code_value/text(), 2)"/>
55
+ <xsl:text>;</xsl:text>
56
+ </mi>
57
+ </xsl:template>
58
+
59
+ <xsl:template match="char[typeface = '6']">
60
+ <mo>
61
+ <xsl:text disable-output-escaping="yes">&amp;#</xsl:text>
62
+ <xsl:value-of select="substring(mt_code_value/text(), 2)"/>
63
+ <xsl:text>;</xsl:text>
64
+ </mo>
65
+ </xsl:template>
66
+
67
+ <xsl:template match="*" />
68
+
69
+ <xsl:template match="tmpl[selector='tmROOT' and variation='tvROOT_NTH']">
70
+ <mroot>
71
+ <xsl:apply-templates select="slot[1]" />
72
+ <xsl:apply-templates select="slot[2]" />
73
+ </mroot>
74
+ </xsl:template>
75
+
76
+ <xsl:template match="tmpl[selector='tmARROW']">
77
+ <munderover accentunder="true">
78
+ <mstyle scriptlevel="-1"><mo>&#x21C0;</mo></mstyle>
79
+ <munder>
80
+ <mstyle scriptlevel="+1"><mo>&#x21BD;</mo></mstyle>
81
+ <xsl:apply-templates select="slot[1]" />
82
+ <xsl:apply-templates select="slot[2]" />
83
+ </munder>
84
+ </munderover>
85
+ </xsl:template>
86
+
87
+ <xsl:template match="tmpl[selector='tmPAREN']">
88
+ <mrow><mo>(</mo>
89
+ <xsl:apply-templates select="slot[1]"/>
90
+ <mo>)</mo></mrow>
91
+ </xsl:template>
92
+
93
+ <xsl:include href="lib/xsl/pile.xsl" />
94
+ <xsl:include href="lib/xsl/char.xsl" />
95
+ <xsl:include href="lib/xsl/embellishment.xsl" />
96
+ <xsl:include href="lib/xsl/subsup.xsl"/>
97
+ <xsl:include href="lib/xsl/sum.xsl"/>
98
+ <xsl:include href="lib/xsl/union_intersection.xsl"/>
99
+ <xsl:include href="lib/xsl/arrow.xsl"/>
100
+ <xsl:include href="lib/xsl/matrix.xsl"/>
101
+ <xsl:include href="lib/xsl/brace.xsl"/>
102
+
103
+
104
+ </xsl:stylesheet>
data/lib/xsl/arrow.xsl ADDED
@@ -0,0 +1,319 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
3
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
4
+ exclude-result-prefixes="xs"
5
+ version="1.0">
6
+
7
+ <!-- Arrows -->
8
+ <xsl:template match="tmpl[selector='tmARROW']">
9
+ <mover>
10
+ <mo>&#x2192;</mo>
11
+ <xsl:apply-templates select="slot[1]"/>
12
+ </mover>
13
+ </xsl:template>
14
+
15
+ <xsl:template match="tmpl[selector='tmARROW' and variation='tvAR_LEFT']">
16
+ <mover>
17
+ <mo>&#x2190;</mo>
18
+ <xsl:apply-templates select="slot[1]"/>
19
+ </mover>
20
+ </xsl:template>
21
+
22
+ <xsl:template match="tmpl[selector='tmARROW' and variation='tvAR_BOTTOM']">
23
+ <munder>
24
+ <mo>&#x2192;</mo>
25
+ <xsl:apply-templates select="slot[2]"/>
26
+ </munder>
27
+ </xsl:template>
28
+
29
+ <xsl:template match="tmpl[selector='tmARROW' and variation='tvAR_TOPBOTTOM']">
30
+ <munderover>
31
+ <mo>&#x2192;</mo>
32
+ <xsl:apply-templates select="slot[2]"/>
33
+ <xsl:apply-templates select="slot[1]"/>
34
+ </munderover>
35
+ </xsl:template>
36
+
37
+ <xsl:template match="tmpl[selector='tmARROW' and variation='tvAR_DOUBLE']">
38
+ <mover>
39
+ <mo>&#x21C4;</mo>
40
+ <xsl:apply-templates select="slot[1]"/>
41
+ </mover>
42
+ </xsl:template>
43
+
44
+ <xsl:template match="tmpl[selector='tmARROW' and (variation='tvAR_LEFT' and variation='tvAR_RIGHT' )]">
45
+ <mover>
46
+ <mo>&#x2194;</mo>
47
+ <xsl:apply-templates select="slot[1]"/>
48
+ </mover>
49
+ </xsl:template>
50
+
51
+ <xsl:template match="tmpl[selector='tmARROW' and variation='tvAR_LEFT' and variation='tvAR_TOPBOTTOM']">
52
+ <munderover>
53
+ <mo>&#x2190;</mo>
54
+ <xsl:apply-templates select="slot[2]"/>
55
+ <xsl:apply-templates select="slot[1]"/>
56
+ </munderover>
57
+ </xsl:template>
58
+
59
+
60
+ <xsl:template match="tmpl[selector='tmARROW' and variation='tvAR_DOUBLE' and variation='tvAR_TOPBOTTOM']">
61
+ <munderover>
62
+ <mo>&#x21C4;</mo>
63
+ <xsl:apply-templates select="slot[2]"/>
64
+ <xsl:apply-templates select="slot[1]"/>
65
+ </munderover>
66
+ </xsl:template>
67
+
68
+ <xsl:template match="tmpl[selector='tmARROW' and variation='tvAR_DOUBLE' and variation='tvAR_LOS']">
69
+ <mover>
70
+ <munder accentunder="true">
71
+ <mstyle scriptlevel="-1"><mo>&#x2192;</mo></mstyle>
72
+ <mstyle scriptlevel="+1"><mo>&#x2190;</mo></mstyle>
73
+ </munder>
74
+ <xsl:apply-templates select="slot[1]"/>
75
+ </mover>
76
+ </xsl:template>
77
+
78
+ <xsl:template match="tmpl[selector='tmARROW' and variation='tvAR_DOUBLE' and variation='tvAR_SOL']">
79
+ <mover>
80
+ <munder accentunder="true">
81
+ <mstyle scriptlevel="+1"><mo>&#x2192;</mo></mstyle>
82
+ <mstyle scriptlevel="-1"><mo>&#x2190;</mo></mstyle>
83
+ </munder>
84
+ <xsl:apply-templates select="slot[1]"/>
85
+ </mover>
86
+ </xsl:template>
87
+
88
+ <xsl:template match="tmpl[selector='tmARROW' and (variation='tvAR_DOUBLE' or variation='tvAR_HARPOON') and variation='tvAR_HARPOON']">
89
+ <mover>
90
+ <mo>&#x21CC;</mo>
91
+ <xsl:apply-templates select="slot[1]"/>
92
+ </mover>
93
+ </xsl:template>
94
+
95
+ <xsl:template match="tmpl[selector='tmARROW' and (variation='tvAR_LEFT' and variation='tvAR_RIGHT' ) and variation='tvAR_TOPBOTTOM']">
96
+ <munderover>
97
+ <mo>&#x2194;</mo>
98
+ <xsl:apply-templates select="slot[2]"/>
99
+ <xsl:apply-templates select="slot[1]"/>
100
+ </munderover>
101
+ </xsl:template>
102
+
103
+
104
+ <xsl:template match="tmpl[selector='tmARROW' and (variation='tvAR_DOUBLE' or variation='tvAR_HARPOON') and variation='tvAR_HARPOON']">
105
+ <mover>
106
+ <mo>&#x21CC;</mo>
107
+ <xsl:apply-templates select="slot[1]"/>
108
+ </mover>
109
+ </xsl:template>
110
+
111
+ <xsl:template match="tmpl[selector='tmARROW' and variation='tvAR_DOUBLE' and variation='tvAR_LOS' and variation='tvAR_TOPBOTTOM']">
112
+ <munderover accentunder="true">
113
+ <mstyle scriptlevel="-1"><mo>&#x2192;</mo></mstyle>
114
+ <munder>
115
+ <mstyle scriptlevel="+1"><mo>&#x2190;</mo></mstyle>
116
+ <xsl:apply-templates select="slot[2]"/>
117
+ </munder>
118
+ <xsl:apply-templates select="slot[1]"/>
119
+ </munderover>
120
+ </xsl:template>
121
+
122
+ <xsl:template match="tmpl[selector='tmARROW' and variation='tvAR_DOUBLE' and variation='tvAR_SOL' and variation='tvAR_TOPBOTTOM']">
123
+ <munderover accentunder="true">
124
+ <mstyle scriptlevel="+1"><mo>&#x2192;</mo></mstyle>
125
+ <munder>
126
+ <mstyle scriptlevel="-1"><mo>&#x2190;</mo></mstyle>
127
+ <xsl:apply-templates select="slot[2]"/>
128
+ </munder>
129
+ <xsl:apply-templates select="slot[1]"/>
130
+ </munderover>
131
+ </xsl:template>
132
+
133
+ <xsl:template match="tmpl[selector='tmARROW' and (variation='tvAR_DOUBLE' or variation='tvAR_HARPOON') and variation='tvAR_HARPOON' and variation='tvAR_SOL']">
134
+ <mover>
135
+ <munder accentunder="true">
136
+ <mstyle scriptlevel="+1"><mo>&#x21C0;</mo></mstyle>
137
+ <mstyle scriptlevel="-1"><mo>&#x21BD;</mo></mstyle>
138
+ </munder>
139
+ <xsl:apply-templates select="slot[1]"/>
140
+ </mover>
141
+ </xsl:template>
142
+
143
+ <xsl:template match="tmpl[selector='tmARROW' and (variation='tvAR_DOUBLE' or variation='tvAR_HARPOON') and variation='tvAR_HARPOON' and variation='tvAR_LOS']">
144
+ <mover>
145
+ <munder accentunder="true">
146
+ <mstyle scriptlevel="-1"><mo>&#x21C0;</mo></mstyle>
147
+ <mstyle scriptlevel="+1"><mo>&#x21BD;</mo></mstyle>
148
+ </munder>
149
+ <xsl:apply-templates select="slot[1]"/>
150
+ </mover>
151
+ </xsl:template>
152
+
153
+ <xsl:template match="tmpl[selector='tmARROW' and (variation='tvAR_DOUBLE' or variation='tvAR_HARPOON') and variation='tvAR_HARPOON' and variation='tvAR_TOPBOTTOM']">
154
+ <munderover>
155
+ <mo>&#x21CC;</mo>
156
+ <xsl:apply-templates select="slot[2]"/>
157
+ <xsl:apply-templates select="slot[1]"/>
158
+ </munderover>
159
+ </xsl:template>
160
+
161
+ <xsl:template match="tmpl[selector='tmARROW' and (variation='tvAR_DOUBLE' or variation='tvAR_HARPOON') and variation='tvAR_HARPOON' and variation='tvAR_LOS' and variation='tvAR_TOPBOTTOM']">
162
+ <munderover accentunder="true">
163
+ <mstyle scriptlevel="-1"><mo>&#x21C0;</mo></mstyle>
164
+ <munder>
165
+ <mstyle scriptlevel="+1"><mo>&#x21BD;</mo></mstyle>
166
+ <xsl:apply-templates select="slot[2]"/>
167
+ </munder>
168
+ <xsl:apply-templates select="slot[1]"/>
169
+ </munderover>
170
+ </xsl:template>
171
+
172
+ <xsl:template match="tmpl[selector='tmARROW' and (variation='tvAR_DOUBLE' or variation='tvAR_HARPOON') and variation='tvAR_HARPOON' and variation='tvAR_SOL' and variation='tvAR_TOPBOTTOM']">
173
+ <munderover accentunder="true">
174
+ <mstyle scriptlevel="+1"><mo>&#x21C0;</mo></mstyle>
175
+ <munder>
176
+ <mstyle scriptlevel="-1"><mo>&#x21BD;</mo></mstyle>
177
+ <xsl:apply-templates select="slot[2]"/>
178
+ </munder>
179
+ <xsl:apply-templates select="slot[1]"/>
180
+ </munderover>
181
+ </xsl:template>
182
+
183
+ <xsl:template match="tmpl[selector='tmARROW' and variation='tvAR_LEFT' and variation='tvAR_BOTTOM']">
184
+ <munder>
185
+ <mo>&#x2190;</mo>
186
+ <xsl:apply-templates select="slot[2]"/>
187
+ </munder>
188
+ </xsl:template>
189
+
190
+ <xsl:template match="tmpl[selector='tmARROW' and (variation='tvAR_LEFT' and variation='tvAR_RIGHT' ) and variation='tvAR_BOTTOM']">
191
+ <munder>
192
+ <mo>&#x2194;</mo>
193
+ <xsl:apply-templates select="slot[2]"/>
194
+ </munder>
195
+ </xsl:template>
196
+
197
+ <xsl:template match="tmpl[selector='tmARROW' and variation='tvAR_DOUBLE' and variation='tvAR_BOTTOM']">
198
+ <munder>
199
+ <mo>&#x21C4;</mo>
200
+ <xsl:apply-templates select="slot[2]"/>
201
+ </munder>
202
+ </xsl:template>
203
+
204
+ <xsl:template match="tmpl[selector='tmARROW' and variation='tvAR_DOUBLE' and variation='tvAR_LOS' and variation='tvAR_BOTTOM']">
205
+ <munder>
206
+ <munder accentunder="true">
207
+ <mstyle scriptlevel="-1"><mo>&#x2192;</mo></mstyle>
208
+ <mstyle scriptlevel="+1"><mo>&#x2190;</mo></mstyle>
209
+ </munder>
210
+ <xsl:apply-templates select="slot[2]"/>
211
+ </munder>
212
+ </xsl:template>
213
+
214
+ <xsl:template match="tmpl[selector='tmARROW' and variation='tvAR_DOUBLE' and variation='tvAR_SOL' and variation='tvAR_BOTTOM']">
215
+ <munder>
216
+ <munder accentunder="true">
217
+ <mstyle scriptlevel="+1"><mo>&#x2192;</mo></mstyle>
218
+ <mstyle scriptlevel="-1"><mo>&#x2190;</mo></mstyle>
219
+ </munder>
220
+ <xsl:apply-templates select="slot[2]"/>
221
+ </munder>
222
+ </xsl:template>
223
+
224
+ <xsl:template match="tmpl[selector='tmARROW' and (variation='tvAR_DOUBLE' or variation='tvAR_HARPOON') and variation='tvAR_HARPOON' and variation='tvAR_BOTTOM']">
225
+ <munder>
226
+ <mo>&#x21CC;</mo>
227
+ <xsl:apply-templates select="slot[2]"/>
228
+ </munder>
229
+ </xsl:template>
230
+
231
+ <xsl:template match="tmpl[selector='tmARROW' and (variation='tvAR_DOUBLE' or variation='tvAR_HARPOON') and variation='tvAR_HARPOON' and variation='tvAR_LOS' and variation='tvAR_BOTTOM']">
232
+ <munder>
233
+ <munder accentunder="true">
234
+ <mstyle scriptlevel="-1"><mo>&#x21C0;</mo></mstyle>
235
+ <mstyle scriptlevel="+1"><mo>&#x21BD;</mo></mstyle>
236
+ </munder>
237
+ <xsl:apply-templates select="slot[2]"/>
238
+ </munder>
239
+ </xsl:template>
240
+
241
+ <xsl:template match="tmpl[selector='tmARROW' and (variation='tvAR_DOUBLE' or variation='tvAR_HARPOON') and variation='tvAR_HARPOON' and variation='tvAR_SOL' and variation='tvAR_BOTTOM']">
242
+ <munder>
243
+ <munder accentunder="true">
244
+ <mstyle scriptlevel="+1"><mo>&#x21C0;</mo></mstyle>
245
+ <mstyle scriptlevel="-1"><mo>&#x21BD;</mo></mstyle>
246
+ </munder>
247
+ <xsl:apply-templates select="slot[2]"/>
248
+ </munder>
249
+ </xsl:template>
250
+
251
+ <xsl:template match="tmpl[selector='tmARROW' and variation='tvAR_LEFT' and variation='tvAR_BOTTOM']">
252
+ <munder>
253
+ <mo>&#x2190;</mo>
254
+ <xsl:apply-templates select="slot[2]"/>
255
+ </munder>
256
+ </xsl:template>
257
+
258
+ <xsl:template match="tmpl[selector='tmARROW' and (variation='tvAR_LEFT' and variation='tvAR_RIGHT' ) and variation='tvAR_BOTTOM']">
259
+ <munder>
260
+ <mo>&#x2194;</mo>
261
+ <xsl:apply-templates select="slot[2]"/>
262
+ </munder>
263
+ </xsl:template>
264
+
265
+ <xsl:template match="tmpl[selector='tmARROW' and variation='tvAR_DOUBLE' and variation='tvAR_BOTTOM']">
266
+ <munder>
267
+ <mo>&#x21C4;</mo>
268
+ <xsl:apply-templates select="slot[2]"/>
269
+ </munder>
270
+ </xsl:template>
271
+
272
+ <xsl:template match="tmpl[selector='tmARROW' and variation='tvAR_DOUBLE' and variation='tvAR_LOS' and variation='tvAR_BOTTOM']">
273
+ <munder>
274
+ <munder accentunder="true">
275
+ <mstyle scriptlevel="-1"><mo>&#x2192;</mo></mstyle>
276
+ <mstyle scriptlevel="+1"><mo>&#x2190;</mo></mstyle>
277
+ </munder>
278
+ <xsl:apply-templates select="slot[2]"/>
279
+ </munder>
280
+ </xsl:template>
281
+
282
+ <xsl:template match="tmpl[selector='tmARROW' and variation='tvAR_DOUBLE' and variation='tvAR_SOL' and variation='tvAR_BOTTOM']">
283
+ <munder>
284
+ <munder accentunder="true">
285
+ <mstyle scriptlevel="+1"><mo>&#x2192;</mo></mstyle>
286
+ <mstyle scriptlevel="-1"><mo>&#x2190;</mo></mstyle>
287
+ </munder>
288
+ <xsl:apply-templates select="slot[2]"/>
289
+ </munder>
290
+ </xsl:template>
291
+
292
+ <xsl:template match="tmpl[selector='tmARROW' and (variation='tvAR_DOUBLE' or variation='tvAR_HARPOON') and variation='tvAR_HARPOON' and variation='tvAR_BOTTOM']">
293
+ <munder>
294
+ <mo>&#x21CC;</mo>
295
+ <xsl:apply-templates select="slot[2]"/>
296
+ </munder>
297
+ </xsl:template>
298
+
299
+ <xsl:template match="tmpl[selector='tmARROW' and (variation='tvAR_DOUBLE' or variation='tvAR_HARPOON') and variation='tvAR_HARPOON' and variation='tvAR_LOS' and variation='tvAR_BOTTOM']">
300
+ <munder>
301
+ <munder accentunder="true">
302
+ <mstyle scriptlevel="-1"><mo>&#x21C0;</mo></mstyle>
303
+ <mstyle scriptlevel="+1"><mo>&#x21BD;</mo></mstyle>
304
+ </munder>
305
+ <xsl:apply-templates select="slot[2]"/>
306
+ </munder>
307
+ </xsl:template>
308
+
309
+ <xsl:template match="tmpl[selector='tmARROW' and (variation='tvAR_DOUBLE' or variation='tvAR_HARPOON') and variation='tvAR_HARPOON' and variation='tvAR_SOL' and variation='tvAR_BOTTOM']">
310
+ <munder>
311
+ <munder accentunder="true">
312
+ <mstyle scriptlevel="+1"><mo>&#x21C0;</mo></mstyle>
313
+ <mstyle scriptlevel="-1"><mo>&#x21BD;</mo></mstyle>
314
+ </munder>
315
+ <xsl:apply-templates select="slot[2]"/>
316
+ </munder>
317
+ </xsl:template>
318
+
319
+ </xsl:stylesheet>