omml2mathml 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 36f0dd7b4d4eb9f4678aa1a41ba9dd82f520f3b9
4
+ data.tar.gz: acad6b14049e8dd73b02033e0ca693c14544b7f1
5
+ SHA512:
6
+ metadata.gz: feeef14dd0fe540da6df7aa44b0f2160b7a5ad7ea575f0dc0c22e0d6dbba3938121fe27bad5184b939dddf171055329646d0ef5c6659ecccf3110f28ff973513
7
+ data.tar.gz: bbd6dc3f8b292a332293aaa8340d1f4e5c3252cc894d74f16ae25c0296804b69b59c48c65eb5f844483b6a30b71aab9dff900d256aa1bd2b7460de2aacd20d7f
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source "https://rubygems.org"
2
+
3
+ group :development, :test do
4
+ gem "rspec"
5
+ gem "rspec-match_fuzzy"
6
+ end
7
+
8
+
9
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
10
+
11
+ # Specify your gem's dependencies in omml2mathml.gemspec
12
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,93 @@
1
+ This software is dual-licensed:
2
+
3
+ 1. Distributed under a Creative Commons Attribution-ShareAlike 3.0
4
+ Unported License http://creativecommons.org/licenses/by-sa/3.0/
5
+
6
+ 2. http://www.opensource.org/licenses/BSD-2-Clause
7
+
8
+ All rights reserved.
9
+
10
+ Redistribution and use in source and binary forms, with or without
11
+ modification, are permitted provided that the following conditions are met:
12
+
13
+ * Redistributions of source code must retain the above copyright notice, this
14
+ list of conditions and the following disclaimer.
15
+
16
+ * Redistributions in binary form must reproduce the above copyright notice,
17
+ this list of conditions and the following disclaimer in the documentation
18
+ and/or other materials provided with the distribution.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+
32
+
33
+
34
+
35
+
36
+ LICENSE FOR STYLESHEETS DERIVED FROM https://github.com/TEIC/Stylesheets
37
+
38
+ This software is dual-licensed:
39
+
40
+ 1. Distributed under a Creative Commons Attribution-ShareAlike 3.0
41
+ Unported License http://creativecommons.org/licenses/by-sa/3.0/
42
+
43
+ 2. http://www.opensource.org/licenses/BSD-2-Clause
44
+
45
+ All rights reserved.
46
+
47
+ Redistribution and use in source and binary forms, with or without
48
+ modification, are permitted provided that the following conditions are
49
+ met:
50
+
51
+ * Redistributions of source code must retain the above copyright
52
+ notice, this list of conditions and the following disclaimer.
53
+
54
+ * Redistributions in binary form must reproduce the above copyright
55
+ notice, this list of conditions and the following disclaimer in the
56
+ documentation and/or other materials provided with the distribution.
57
+
58
+ This software is provided by the copyright holders and contributors
59
+ "as is" and any express or implied warranties, including, but not
60
+ limited to, the implied warranties of merchantability and fitness for
61
+ a particular purpose are disclaimed. In no event shall the copyright
62
+ holder or contributors be liable for any direct, indirect, incidental,
63
+ special, exemplary, or consequential damages (including, but not
64
+ limited to, procurement of substitute goods or services; loss of use,
65
+ data, or profits; or business interruption) however caused and on any
66
+ theory of liability, whether in contract, strict liability, or tort
67
+ (including negligence or otherwise) arising in any way out of the use
68
+ of this software, even if advised of the possibility of such damage.
69
+
70
+
71
+
72
+
73
+ LICENSE FOR STYLESHEETS DERIVED FROM https://github.com/davidcarlisle/web-xslt
74
+
75
+ https://www.w3.org/Consortium/Legal/copyright-software-19980720
76
+
77
+ W3C® SOFTWARE NOTICE AND LICENSE
78
+
79
+ Copyright © 1994-2002 World Wide Web Consortium, (Massachusetts Institute of Technology, Institut National de Recherche en Informatique et en Automatique, Keio University). All Rights Reserved. http://www.w3.org/Consortium/Legal/
80
+
81
+ This W3C work (including software, documents, or other related items) is being provided by the copyright holders under the following license. By obtaining, using and/or copying this work, you (the licensee) agree that you have read, understood, and will comply with the following terms and conditions:
82
+
83
+ Permission to use, copy, modify, and distribute this software and its documentation, with or without modification, for any purpose and without fee or royalty is hereby granted, provided that you include the following on ALL copies of the software and documentation or portions thereof, including modifications, that you make:
84
+
85
+ The full text of this NOTICE in a location viewable to users of the redistributed or derivative work.
86
+ Any pre-existing intellectual property disclaimers, notices, or terms and conditions. If none exist, a short notice of the following form (hypertext is preferred, text is permitted) should be used within the body of any redistributed or derivative code: "Copyright © [$date-of-software] World Wide Web Consortium, (Massachusetts Institute of Technology, Institut National de Recherche en Informatique et en Automatique, Keio University). All Rights Reserved. http://www.w3.org/Consortium/Legal/"
87
+ Notice of any changes or modifications to the W3C files, including the date changes were made. (We recommend you provide URIs to the location from which the code is derived.)
88
+ THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
89
+
90
+ COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENTATION.
91
+
92
+ The name and trademarks of copyright holders may NOT be used in advertising or publicity pertaining to the software without specific, written prior permission. Title to copyright in this software and any associated documentation will at all times remain with copyright holders.
93
+
data/README.adoc ADDED
@@ -0,0 +1,23 @@
1
+ = omml2mathml
2
+ Convert Office Math Markup to MathML
3
+
4
+ This is a Ruby gem for converting Office Math Markup (OMML) into MathML within Word HTML documents.
5
+
6
+ The smarts of this gem comes from different sources:
7
+
8
+ * Most of the conversion of the OMML conversion is done by the `omml2mml.xsl` stylesheet. This is a
9
+ prerelease version of the `omml2mathml.xsl` that currently ships with Microsoft Word, and which is how Word allows
10
+ you to copy-paste MathML out of Word. The `omml2mml.xsl` version of the stylesheet has been published for several years now as part of the https://github.com/TEIC/Stylesheets[TEI stylesheet set]. (We have made some minor edits to the stylesheet, downgrading it from XSLT v2 to v1.) The stylesheets have been published under a dual Creative Commons Sharealike/BSD licence.
11
+
12
+ * The `omml2mml.xsl` stylesheet does most of the conversion; the remainder is done by the `xhtml-mathml.xsl` stylesheet, created by David Carlisle in 2007 (and https://github.com/davidcarlisle/web-xslt/tree/master/omml2mml[available on Github]). We have done some minor edits to this stylesheet too, downgrading it from XSLT v2 to v1 and removing some functionality in the process; the MathML itself is unaffected.
13
+
14
+ The gem also converts any file it processes from HTML to XHTML, so that the stylesheets can deal with it. In the process, it needs to restore the casing of OOXML tags, which are case-sensitive.
15
+
16
+ == Usage
17
+
18
+ [source,ruby]
19
+ ----
20
+ require "omml2mathml"
21
+
22
+ html = Ooml2Mathml.convert("Word.html")
23
+ ----
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "html2doc"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/rspec ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rspec' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require "pathname"
10
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path(
11
+ "../../Gemfile", Pathname.new(__FILE__).realpath
12
+ )
13
+
14
+ require "rubygems"
15
+ require "bundler/setup"
16
+
17
+ load Gem.bin_path("rspec-core", "rspec")
18
+
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,4 @@
1
+ module Omml2Mathml
2
+ require_relative "omml2mathml/version"
3
+ require_relative "omml2mathml/convert"
4
+ end
@@ -0,0 +1,186 @@
1
+ require "xml/xslt"
2
+ require "nokogiri"
3
+
4
+ module Omml2Mathml
5
+ module_function
6
+ def convert(filename)
7
+ @tags = %w{
8
+ acc
9
+ accPr
10
+ aln
11
+ alnScr
12
+ argPr
13
+ argSz
14
+ bar
15
+ barPr
16
+ baseJc
17
+ begChr
18
+ borderBox
19
+ borderBoxPr
20
+ box
21
+ boxPr
22
+ brk
23
+ brkBin
24
+ brkBinSub
25
+ cGp
26
+ cGpRule
27
+ chr
28
+ count
29
+ cSp
30
+ ctrlPr
31
+ d
32
+ defJc
33
+ deg
34
+ degHide
35
+ den
36
+ diff
37
+ dispDef
38
+ dPr
39
+ e
40
+ endChr
41
+ eqArr
42
+ eqArrPr
43
+ f
44
+ fName
45
+ fPr
46
+ func
47
+ funcPr
48
+ groupChr
49
+ groupChrPr
50
+ grow
51
+ hideBot
52
+ hideLeft
53
+ hideRight
54
+ hideTop
55
+ interSp
56
+ intLim
57
+ intraSp
58
+ jc
59
+ lim
60
+ limLoc
61
+ limLow
62
+ limLowPr
63
+ limUpp
64
+ limUppPr
65
+ lit
66
+ lMargin
67
+ m
68
+ mathFont
69
+ mathPr
70
+ maxDist
71
+ mc
72
+ mcJc
73
+ mcPr
74
+ mcs
75
+ mPr
76
+ mr
77
+ nary
78
+ naryLim
79
+ naryPr
80
+ noBreak
81
+ nor
82
+ num
83
+ objDist
84
+ oMath
85
+ oMathPara
86
+ oMathParaPr
87
+ opEmu
88
+ phant
89
+ phantPr
90
+ plcHide
91
+ pos
92
+ postSp
93
+ preSp
94
+ r
95
+ rad
96
+ radPr
97
+ rMargin
98
+ rPr
99
+ rSp
100
+ rSpRule
101
+ scr
102
+ sepChr
103
+ show
104
+ shp
105
+ smallFrac
106
+ sPre
107
+ sPrePr
108
+ sSub
109
+ sSubPr
110
+ sSubSup
111
+ sSubSupPr
112
+ sSup
113
+ sSupPr
114
+ strikeBLTR
115
+ strikeH
116
+ strikeTLBR
117
+ strikeV
118
+ sty
119
+ sub
120
+ subHide
121
+ sup
122
+ supHide
123
+ t
124
+ transp
125
+ type
126
+ vertJc
127
+ wrapIndent
128
+ wrapRight
129
+ zeroAsc
130
+ zeroDesc
131
+ zeroWid
132
+ }
133
+
134
+ @mathml = {}
135
+ @tags.each do |t|
136
+ @mathml["m_#{t.downcase}"] = "m:#{t}"
137
+ end
138
+
139
+ html = Nokogiri::HTML.parse(File.read(filename, encoding: "utf-8").
140
+ gsub(/\r/, "").gsub(/<m:/, "<m_").
141
+ gsub(/<\/m:/, "</m_").
142
+ gsub(/<!\[if !msEquation\]>/,
143
+ "<!--if !msEquation-->"))
144
+ @xslt = XML::XSLT.new
145
+ @xslt.xsl = File.join(File.dirname(__FILE__), "xhtml-mathml.xsl")
146
+ html.traverse do |n|
147
+ if n.comment?
148
+ if /^\[if gte msEquation 12\]>/.match? n.text
149
+ n.replace(n.text.sub(/\[if gte msEquation 12\]>/, "").
150
+ sub(/<!\[endif\]/, ""))
151
+ elsif /^if !msEquation/.match? n.text
152
+ n.next.remove
153
+ n.remove
154
+ else
155
+ n.remove
156
+ end
157
+ end
158
+ end
159
+ xml = Nokogiri::XML(html.to_xhtml)
160
+ xml.traverse do |t|
161
+ if t.element? && @mathml.has_key?(t.name)
162
+ t.name = @mathml[t.name]
163
+ end
164
+ end
165
+ #xml.xpath("//xmlns:link | //xmlns:style | //*[@class = 'MsoToc1'] | //*[@class = 'MsoToc2'] |//*[@class = 'MsoToc3'] |//*[@class = 'MsoToc4'] |//*[@class = 'MsoToc5'] |//*[@class = 'MsoToc6'] |//*[@class = 'MsoToc7'] |//*[@class = 'MsoToc8'] |//*[@class = 'MsoToc9'] ").each { |x| x.remove }
166
+ xml.xpath("//*").each do |x|
167
+ if x.name == "m:oMath" || x.name == "m:oMathPara"
168
+ @xslt.xml = x.to_xml.
169
+ sub(/<m:(oMath|oMathPara)>/,
170
+ "<m:\\1 xmlns:m='http://schemas.openxmlformats.org/officeDocument/2006/math'>")
171
+ out = @xslt.serve
172
+ mml = out.gsub(/<\?xml[^>]+>/, '').
173
+ gsub(%r{<([^:/! >]+ xmlns="http://www.w3.org/1998/Math/MathML")},
174
+ "<mml:\\1").
175
+ gsub(%r{<([^:/!>]+)>}, "<mml:\\1>").
176
+ gsub(%r{</([^:/!>]+)>}, "</mml:\\1>").
177
+ gsub(%r{ xmlns="http://www.w3.org/1998/Math/MathML"}, "").
178
+ gsub(%r{ xmlns:mml="http://www.w3.org/1998/Math/MathML"}, "").
179
+ gsub(%r{ xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"}, "").
180
+ gsub(%r{ xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math"}, "")
181
+ x.replace("<mml:math>#{mml}</mml:math>")
182
+ end
183
+ end
184
+ xml.to_s
185
+ end
186
+ end
@@ -0,0 +1,1821 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!-- Beta Version 070708 -->
3
+ <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
4
+ xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
5
+ xmlns="http://www.w3.org/1998/Math/MathML"
6
+ xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math"
7
+ version="1.0">
8
+ <!--
9
+ version="2.0"
10
+ exclude-result-prefixes="m w"> -->
11
+ <!-- %% Global Definitions -->
12
+
13
+ <!-- Every single unicode character that is recognized by OMML as an operator -->
14
+ <xsl:variable name="sOperators"
15
+ select="concat( '!&#34;#&amp;()+,-./:', ';&lt;=&gt;?@[\]^_{', '|}~¡¦¬¯°±²³·¹¿', '×÷̀́̂̃̄̅̆̇̈̉', '̊̋̌̍̎̏̐̑̒̓̔̕', '̡̛̖̗̘̙̜̝̞̟̠̚', '̢̧̨̣̤̥̦̩̪̫̬̭', '̴̵̶̷̸̮̯̰̱̲̳̿', '         ‐‒–', '—‖†‡•․‥…′″‴‼', '⁀⁄⁎⁏⁐⁗⁡⁢⁣⁰⁴⁵', '⁶⁷⁸⁹⁺⁻⁼⁽⁾₀₁₂', '₃₄₅₆₇₈₉₊₋₌₍₎', '⃒⃓⃘⃙⃚⃐⃑⃔⃕⃖⃗⃛', '⃜⃝⃞⃟⃠⃡⃤⃥⃦⃨⃧⃩', '⃪⅀ࡢ←↑→↓↔↕↖↗↘↙', '↚↛↜↝↞↟↠↡↢↣↤↥', '↦↧↨↩↪↫↬↭↮↯↰↱', '↲↳↶↷↺↻↼↽↾↿⇀⇁', '⇂⇃⇄⇅⇆⇇⇈⇉⇊⇋⇌⇍', '⇎⇏⇐⇑⇒⇓⇔⇕⇖⇗⇘⇙', '⇚⇛⇜⇝⇞⇟⇠⇡⇢⇣⇤⇥', '⇦⇧⇨⇩⇳⇴⇵⇶⇷⇸⇹⇺', '⇻⇼⇽⇾⇿∀∁∂∃∄∆∇', '∈∉∊∋∌∍∏∐∑−∓∔', '∕∖∗∘∙√∛∜∝∣∤∥', '∦∧∨∩∪∫∬∭∮∯∰∱', '∲∳∴∵∶∷∸∹∺∻∼∽', '∾≀≁≂≃≄≅≆≇≈≉≊', '≋≌≍≎≏≐≑≒≓≔≕≖', '≗≘≙≚≛≜≝≞≟≠≡≢', '≣≤≥≦≧≨≩≪≫≬≭≮', '≯≰≱≲≳≴≵≶≷≸≹≺', '≻≼≽≾≿⊀⊁⊂⊃⊄⊅⊆', '⊇⊈⊉⊊⊋⊌⊍⊎⊏⊐⊑⊒', '⊓⊔⊕⊖⊗⊘⊙⊚⊛⊜⊝⊞', '⊟⊠⊡⊢⊣⊥⊦⊧⊨⊩⊪⊫', '⊬⊭⊮⊯⊰⊱⊲⊳⊴⊵⊶⊷', '⊸⊹⊺⊻⊼⊽⋀⋁⋂⋃⋄⋅', '⋆⋇⋈⋉⋊⋋⋌⋍⋎⋏⋐⋑', '⋒⋓⋔⋕⋖⋗⋘⋙⋚⋛⋜⋝', '⋞⋟⋠⋡⋢⋣⋤⋥⋦⋧⋨⋩', '⋪⋫⋬⋭⋮⋯⋰⋱⋲⋳⋴⋵', '⋶⋷⋸⋹⋺⋻⋼⋽⋾⋿⌅⌆', '⌈⌉⌊⌋⌜⌝⌞⌟⌢⌣〈〉', '⌽⌿⎰⎱⏜⏝⏞⏟⏠│├┤', '┬┴▁█▒■□▭▲△▴▵', '▶▷▸▹▼▽▾▿◀◁◂◃', '◄◅◊○◦◫◬◸◹◺◻◼', '◽◾◿★☆❲❳⟑⟒⟓⟔⟕', '⟖⟗⟘⟙⟚⟛⟜⟝⟞⟟⟠⟡', '⟢⟣⟤⟥⟦⟧⟨⟩⟪⟫⟰⟱', '⟲⟳⟴⟵⟶⟷⟸⟹⟺⟻⟼⟽', '⟾⟿⤀⤁⤂⤃⤄⤅⤆⤇⤈⤉', '⤊⤋⤌⤍⤎⤏⤐⤑⤒⤓⤔⤕', '⤖⤗⤘⤙⤚⤛⤜⤝⤞⤟⤠⤡', '⤢⤣⤤⤥⤦⤧⤨⤩⤪⤫⤬⤭', '⤮⤯⤰⤱⤲⤳⤴⤵⤶⤷⤸⤹', '⤺⤻⤼⤽⤾⤿⥀⥁⥂⥃⥄⥅', '⥆⥇⥈⥉⥊⥋⥌⥍⥎⥏⥐⥑', '⥒⥓⥔⥕⥖⥗⥘⥙⥚⥛⥜⥝', '⥞⥟⥠⥡⥢⥣⥤⥥⥦⥧⥨⥩', '⥪⥫⥬⥭⥮⥯⥰⥱⥲⥳⥴⥵', '⥶⥷⥸⥹⥺⥻⥼⥽⥾⥿⦀⦂', '⦃⦄⦅⦆⦇⦈⦉⦊⦋⦌⦍⦎', '⦏⦐⦑⦒⦓⦔⦕⦖⦗⦘⦙⦚', '⦶⦷⦸⦹⧀⧁⧄⧅⧆⧇⧈⧎', '⧏⧐⧑⧒⧓⧔⧕⧖⧗⧘⧙⧚', '⧛⧟⧡⧢⧣⧤⧥⧦⧫⧴⧵⧶', '⧷⧸⧹⧺⧻⧼⧽⧾⧿⨀⨁⨂', '⨃⨄⨅⨆⨇⨈⨉⨊⨋⨌⨍⨎', '⨏⨐⨑⨒⨓⨔⨕⨖⨗⨘⨙⨚', '⨛⨜⨝⨞⨟⨠⨡⨢⨣⨤⨥⨦', '⨧⨨⨩⨪⨫⨬⨭⨮⨯⨰⨱⨲', '⨳⨴⨵⨶⨷⨸⨹⨺⨻⨼⨽⨾', '⨿⩀⩁⩂⩃⩄⩅⩆⩇⩈⩉⩊', '⩋⩌⩍⩎⩏⩐⩑⩒⩓⩔⩕⩖', '⩗⩘⩙⩚⩛⩜⩝⩞⩟⩠⩡⩢', '⩣⩤⩥⩦⩧⩨⩩⩪⩫⩬⩭⩮', '⩯⩰⩱⩲⩳⩴⩵⩶⩷⩸⩹⩺', '⩻⩼⩽⩾⩿⪀⪁⪂⪃⪄⪅⪆', '⪇⪈⪉⪊⪋⪌⪍⪎⪏⪐⪑⪒', '⪓⪔⪕⪖⪗⪘⪙⪚⪛⪜⪝⪞', '⪟⪠⪡⪢⪣⪤⪥⪦⪧⪨⪩⪪', '⪫⪬⪭⪮⪯⪰⪱⪲⪳⪴⪵⪶', '⪷⪸⪹⪺⪻⪼⪽⪾⪿⫀⫁⫂', '⫃⫄⫅⫆⫇⫈⫉⫊⫋⫌⫍⫎', '⫏⫐⫑⫒⫓⫔⫕⫖⫗⫘⫙⫚', '⫛⫝̸⫝⫞⫟⫠⫢⫣⫤⫥⫦⫧', '⫨⫩⫪⫫⫬⫭⫮⫯⫰⫲⫳⫴', '⫵⫶⫷⫸⫹⫺⫻⫼⫽⫾⫿⬄', '⬆⬇⬌⬍〔〕〖〗〘〙!&', '()+,-./:;<=>', '?@[\]^_{|}')"/>
16
+
17
+ <!-- A string of '-'s repeated exactly as many times as the operators above -->
18
+ <xsl:variable name="sMinuses">
19
+ <xsl:call-template name="SRepeatChar">
20
+ <xsl:with-param name="cchRequired" select="string-length($sOperators)"/>
21
+ <xsl:with-param name="ch" select="'-'"/>
22
+ </xsl:call-template>
23
+ </xsl:variable>
24
+
25
+ <!-- Every single unicode character that is recognized by OMML as a number -->
26
+ <xsl:variable name="sNumbers" select="'0123456789'"/>
27
+
28
+ <!-- A string of '0's repeated exactly as many times as the list of numbers above -->
29
+ <xsl:variable name="sZeros">
30
+ <xsl:call-template name="SRepeatChar">
31
+ <xsl:with-param name="cchRequired" select="string-length($sNumbers)"/>
32
+ <xsl:with-param name="ch" select="'0'"/>
33
+ </xsl:call-template>
34
+ </xsl:variable>
35
+
36
+ <!-- %%Template: SReplace
37
+
38
+ Replace all occurences of sOrig in sInput with sReplacement
39
+ and return the resulting string. -->
40
+ <xsl:template name="SReplace">
41
+ <xsl:param name="sInput"/>
42
+ <xsl:param name="sOrig"/>
43
+ <xsl:param name="sReplacement"/>
44
+
45
+ <xsl:choose>
46
+ <xsl:when test="not(contains($sInput, $sOrig))">
47
+ <xsl:value-of select="$sInput"/>
48
+ </xsl:when>
49
+ <xsl:otherwise>
50
+ <xsl:variable name="sBefore" select="substring-before($sInput, $sOrig)"/>
51
+ <xsl:variable name="sAfter" select="substring-after($sInput, $sOrig)"/>
52
+ <xsl:variable name="sAfterProcessed">
53
+ <xsl:call-template name="SReplace">
54
+ <xsl:with-param name="sInput" select="$sAfter"/>
55
+ <xsl:with-param name="sOrig" select="$sOrig"/>
56
+ <xsl:with-param name="sReplacement" select="$sReplacement"/>
57
+ </xsl:call-template>
58
+ </xsl:variable>
59
+
60
+ <xsl:value-of select="concat($sBefore, concat($sReplacement, $sAfterProcessed))"/>
61
+ </xsl:otherwise>
62
+ </xsl:choose>
63
+ </xsl:template>
64
+
65
+ <!-- Templates -->
66
+ <!--
67
+ <xsl:template match="/">
68
+ <math>
69
+ <xsl:apply-templates select="*" />
70
+ </math>
71
+ </xsl:template>
72
+ -->
73
+ <xsl:template match="m:borderBox">
74
+
75
+ <!-- Get Lowercase versions of properties -->
76
+ <xsl:variable name="sLowerCaseHideTop"
77
+ select="translate(m:borderBoxPr[last()]/m:hideTop[last()]/@m:val, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
78
+ <xsl:variable name="sLowerCaseHideBot"
79
+ select="translate(m:borderBoxPr[last()]/m:hideBot[last()]/@m:val, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
80
+ <xsl:variable name="sLowerCaseHideLeft"
81
+ select="translate(m:borderBoxPr[last()]/m:hideLeft[last()]/@m:val, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
82
+ <xsl:variable name="sLowerCaseHideRight"
83
+ select="translate(m:borderBoxPr[last()]/m:hideRight[last()]/@m:val, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
84
+ <xsl:variable name="sLowerCaseStrikeH"
85
+ select="translate(m:borderBoxPr[last()]/m:strikeH[last()]/@m:val, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
86
+ <xsl:variable name="sLowerCaseStrikeV"
87
+ select="translate(m:borderBoxPr[last()]/m:strikeV[last()]/@m:val, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
88
+ <xsl:variable name="sLowerCaseStrikeBLTR"
89
+ select="translate(m:borderBoxPr[last()]/m:strikeBLTR[last()]/@m:val, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
90
+ <xsl:variable name="sLowerCaseStrikeTLBR"
91
+ select="translate(m:borderBoxPr[last()]/m:strikeTLBR[last()]/@m:val, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
92
+ <xsl:variable name="fHideTop">
93
+ <xsl:choose>
94
+ <xsl:when test="$sLowerCaseHideTop='on'">
95
+ <xsl:text>1</xsl:text>
96
+ </xsl:when>
97
+ <xsl:otherwise>
98
+ <xsl:text>0</xsl:text>
99
+ </xsl:otherwise>
100
+ </xsl:choose>
101
+ </xsl:variable>
102
+ <xsl:variable name="fHideBot">
103
+ <xsl:choose>
104
+ <xsl:when test="$sLowerCaseHideBot='on'">
105
+ <xsl:text>1</xsl:text>
106
+ </xsl:when>
107
+ <xsl:otherwise>
108
+ <xsl:text>0</xsl:text>
109
+ </xsl:otherwise>
110
+ </xsl:choose>
111
+ </xsl:variable>
112
+ <xsl:variable name="fHideLeft">
113
+ <xsl:choose>
114
+ <xsl:when test="$sLowerCaseHideLeft='on'">
115
+ <xsl:text>1</xsl:text>
116
+ </xsl:when>
117
+ <xsl:otherwise>
118
+ <xsl:text>0</xsl:text>
119
+ </xsl:otherwise>
120
+ </xsl:choose>
121
+ </xsl:variable>
122
+ <xsl:variable name="fHideRight">
123
+ <xsl:choose>
124
+ <xsl:when test="$sLowerCaseHideRight='on'">
125
+ <xsl:text>1</xsl:text>
126
+ </xsl:when>
127
+ <xsl:otherwise>
128
+ <xsl:text>0</xsl:text>
129
+ </xsl:otherwise>
130
+ </xsl:choose>
131
+ </xsl:variable>
132
+ <xsl:variable name="fStrikeH">
133
+ <xsl:choose>
134
+ <xsl:when test="$sLowerCaseStrikeH='on'">
135
+ <xsl:text>1</xsl:text>
136
+ </xsl:when>
137
+ <xsl:otherwise>
138
+ <xsl:text>0</xsl:text>
139
+ </xsl:otherwise>
140
+ </xsl:choose>
141
+ </xsl:variable>
142
+ <xsl:variable name="fStrikeV">
143
+ <xsl:choose>
144
+ <xsl:when test="$sLowerCaseStrikeV='on'">
145
+ <xsl:text>1</xsl:text>
146
+ </xsl:when>
147
+ <xsl:otherwise>
148
+ <xsl:text>0</xsl:text>
149
+ </xsl:otherwise>
150
+ </xsl:choose>
151
+ </xsl:variable>
152
+ <xsl:variable name="fStrikeBLTR">
153
+ <xsl:choose>
154
+ <xsl:when test="$sLowerCaseStrikeBLTR='on'">
155
+ <xsl:text>1</xsl:text>
156
+ </xsl:when>
157
+ <xsl:otherwise>
158
+ <xsl:text>0</xsl:text>
159
+ </xsl:otherwise>
160
+ </xsl:choose>
161
+ </xsl:variable>
162
+ <xsl:variable name="fStrikeTLBR">
163
+ <xsl:choose>
164
+ <xsl:when test="$sLowerCaseStrikeTLBR='on'">
165
+ <xsl:text>1</xsl:text>
166
+ </xsl:when>
167
+ <xsl:otherwise>
168
+ <xsl:text>0</xsl:text>
169
+ </xsl:otherwise>
170
+ </xsl:choose>
171
+ </xsl:variable>
172
+
173
+ <menclose>
174
+ <xsl:call-template name="CreateMencloseNotationAttrFromBorderBoxAttr">
175
+ <xsl:with-param name="fHideTop" select="$fHideTop"/>
176
+ <xsl:with-param name="fHideBot" select="$fHideBot"/>
177
+ <xsl:with-param name="fHideLeft" select="$fHideLeft"/>
178
+ <xsl:with-param name="fHideRight" select="$fHideRight"/>
179
+ <xsl:with-param name="fStrikeH" select="$fStrikeH"/>
180
+ <xsl:with-param name="fStrikeV" select="$fStrikeV"/>
181
+ <xsl:with-param name="fStrikeBLTR" select="$fStrikeBLTR"/>
182
+ <xsl:with-param name="fStrikeTLBR" select="$fStrikeTLBR"/>
183
+ </xsl:call-template>
184
+ <xsl:apply-templates select="m:e[1]"/>
185
+ </menclose>
186
+ </xsl:template>
187
+
188
+ <xsl:template match="*">
189
+ <xsl:apply-templates select="*"/>
190
+ </xsl:template>
191
+
192
+ <xsl:template match="m:acc">
193
+ <mover>
194
+ <xsl:attribute name="accent">true</xsl:attribute>
195
+ <mrow>
196
+ <xsl:apply-templates select="m:e[1]"/>
197
+ </mrow>
198
+ <xsl:variable name="chAcc">
199
+ <xsl:choose>
200
+ <xsl:when test="not(m:accPr[last()]/m:chr)">
201
+ <xsl:value-of select="'̂'"/>
202
+ </xsl:when>
203
+ <xsl:otherwise>
204
+ <xsl:value-of select="substring(m:accPr/m:chr/@m:val,1,1)"/>
205
+ </xsl:otherwise>
206
+ </xsl:choose>
207
+ </xsl:variable>
208
+ <xsl:call-template name="ParseMt">
209
+ <xsl:with-param name="sToParse" select="$chAcc"/>
210
+ <xsl:with-param name="scr" select="m:e[1]/*/m:rPr[last()]/m:scr/@m:val"/>
211
+ <xsl:with-param name="sty" select="m:e[1]/*/m:rPr[last()]/m:sty/@m:val"/>
212
+ <xsl:with-param name="nor" select="m:e[1]/*/m:rPr[last()]/m:nor/@m:val"/>
213
+ </xsl:call-template>
214
+ </mover>
215
+ </xsl:template>
216
+
217
+ <xsl:template match="m:sPre">
218
+ <mmultiscripts>
219
+ <mrow>
220
+ <xsl:apply-templates select="m:e[1]"/>
221
+ </mrow>
222
+ <mprescripts/>
223
+ <mrow>
224
+ <xsl:apply-templates select="m:sub[1]"/>
225
+ </mrow>
226
+ <mrow>
227
+ <xsl:apply-templates select="m:sup[1]"/>
228
+ </mrow>
229
+ </mmultiscripts>
230
+ </xsl:template>
231
+
232
+ <xsl:template match="m:m">
233
+ <mtable>
234
+ <xsl:call-template name="CreateMathMLMatrixAttr">
235
+ <xsl:with-param name="mcJc" select="m:mPr[last()]/m:mcs/m:mc/m:mcPr[last()]/m:mcJc/@m:val"/>
236
+ </xsl:call-template>
237
+ <xsl:for-each select="m:mr">
238
+ <mtr>
239
+ <xsl:for-each select="m:e">
240
+ <mtd>
241
+ <xsl:apply-templates select="."/>
242
+ </mtd>
243
+ </xsl:for-each>
244
+ </mtr>
245
+ </xsl:for-each>
246
+ </mtable>
247
+ </xsl:template>
248
+
249
+ <xsl:template name="CreateMathMLMatrixAttr">
250
+ <xsl:param name="mcJc"/>
251
+ <xsl:variable name="sLowerCaseMcjc"
252
+ select="translate($mcJc, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
253
+ <xsl:choose>
254
+ <xsl:when test="$sLowerCaseMcjc='left'">
255
+ <xsl:attribute name="columnalign">left</xsl:attribute>
256
+ </xsl:when>
257
+ <xsl:when test="$sLowerCaseMcjc='right'">
258
+ <xsl:attribute name="columnalign">right</xsl:attribute>
259
+ </xsl:when>
260
+ </xsl:choose>
261
+ </xsl:template>
262
+
263
+ <xsl:template match="m:phant">
264
+ <xsl:variable name="sLowerCaseZeroWidVal"
265
+ select="translate(m:phantPr[last()]/m:zeroWid[last()]/@m:val, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
266
+ <xsl:variable name="sLowerCaseZeroAscVal"
267
+ select="translate(m:phantPr[last()]/m:zeroAsc[last()]/@m:val, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
268
+ <xsl:variable name="sLowerCaseZeroDescVal"
269
+ select="translate(m:phantPr[last()]/m:zeroDesc[last()]/@m:val, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
270
+ <xsl:variable name="sLowerCaseShowVal"
271
+ select="translate(m:phantPr[last()]/m:show[last()]/@m:val, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
272
+
273
+
274
+ <!-- The following properties default to 'yes' unless the last value equals 'no' or there isn't any node for
275
+ the property -->
276
+
277
+ <xsl:variable name="fZeroWid">
278
+ <xsl:choose>
279
+ <xsl:when test="count(m:phantPr[last()]/m:zeroWid[last()]) = 0">0</xsl:when>
280
+ <xsl:when test="$sLowerCaseZeroWidVal = 'off'">0</xsl:when>
281
+ <xsl:otherwise>1</xsl:otherwise>
282
+ </xsl:choose>
283
+ </xsl:variable>
284
+ <xsl:variable name="fZeroAsc">
285
+ <xsl:choose>
286
+ <xsl:when test="count(m:phantPr[last()]/m:zeroAsc[last()]) = 0">0</xsl:when>
287
+ <xsl:when test="$sLowerCaseZeroAscVal = 'off'">0</xsl:when>
288
+ <xsl:otherwise>1</xsl:otherwise>
289
+ </xsl:choose>
290
+ </xsl:variable>
291
+ <xsl:variable name="fZeroDesc">
292
+ <xsl:choose>
293
+ <xsl:when test="count(m:phantPr[last()]/m:zeroDesc[last()]) = 0">0</xsl:when>
294
+ <xsl:when test="$sLowerCaseZeroDescVal = 'off'">0</xsl:when>
295
+ <xsl:otherwise>1</xsl:otherwise>
296
+ </xsl:choose>
297
+ </xsl:variable>
298
+
299
+ <!-- The show property defaults to 'on' unless there exists a show property and its value is 'off' -->
300
+
301
+ <xsl:variable name="fShow">
302
+ <xsl:choose>
303
+ <xsl:when test="$sLowerCaseShowVal = 'off'">0</xsl:when>
304
+ <xsl:otherwise>1</xsl:otherwise>
305
+ </xsl:choose>
306
+ </xsl:variable>
307
+
308
+ <xsl:choose>
309
+ <!-- Show the phantom contents, therefore, just use mpadded. -->
310
+ <xsl:when test="$fShow = 1">
311
+ <xsl:element name="mpadded">
312
+ <xsl:call-template name="CreateMpaddedAttributes">
313
+ <xsl:with-param name="fZeroWid" select="$fZeroWid"/>
314
+ <xsl:with-param name="fZeroAsc" select="$fZeroAsc"/>
315
+ <xsl:with-param name="fZeroDesc" select="$fZeroDesc"/>
316
+ </xsl:call-template>
317
+ <mrow>
318
+ <xsl:apply-templates select="m:e"/>
319
+ </mrow>
320
+ </xsl:element>
321
+ </xsl:when>
322
+ <!-- Don't show phantom contents, but don't smash anything, therefore, just
323
+ use mphantom -->
324
+ <xsl:when test="$fZeroWid=0 and $fZeroAsc=0 and $fZeroDesc=0">
325
+ <xsl:element name="mphantom">
326
+ <mrow>
327
+ <xsl:apply-templates select="m:e"/>
328
+ </mrow>
329
+ </xsl:element>
330
+ </xsl:when>
331
+ <!-- Combination -->
332
+ <xsl:otherwise>
333
+ <xsl:element name="mphantom">
334
+ <xsl:element name="mpadded">
335
+ <xsl:call-template name="CreateMpaddedAttributes">
336
+ <xsl:with-param name="fZeroWid" select="$fZeroWid"/>
337
+ <xsl:with-param name="fZeroAsc" select="$fZeroAsc"/>
338
+ <xsl:with-param name="fZeroDesc" select="$fZeroDesc"/>
339
+ </xsl:call-template>
340
+ <mrow>
341
+ <xsl:apply-templates select="m:e"/>
342
+ </mrow>
343
+ </xsl:element>
344
+ </xsl:element>
345
+ </xsl:otherwise>
346
+ </xsl:choose>
347
+ </xsl:template>
348
+
349
+ <xsl:template name="CreateMpaddedAttributes">
350
+ <xsl:param name="fZeroWid"/>
351
+ <xsl:param name="fZeroAsc"/>
352
+ <xsl:param name="fZeroDesc"/>
353
+
354
+ <xsl:if test="$fZeroWid=1">
355
+ <xsl:attribute name="width">0</xsl:attribute>
356
+ </xsl:if>
357
+ <xsl:if test="$fZeroAsc=1">
358
+ <xsl:attribute name="height">0</xsl:attribute>
359
+ </xsl:if>
360
+ <xsl:if test="$fZeroDesc=1">
361
+ <xsl:attribute name="depth">0</xsl:attribute>
362
+ </xsl:if>
363
+ </xsl:template>
364
+
365
+
366
+
367
+ <xsl:template match="m:rad">
368
+ <xsl:variable name="sLowerCaseDegHide"
369
+ select="translate(m:radPr[last()]/m:degHide/@m:val, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
370
+ <xsl:choose>
371
+ <xsl:when test="$sLowerCaseDegHide='on'">
372
+ <msqrt>
373
+ <xsl:apply-templates select="m:e[1]"/>
374
+ </msqrt>
375
+ </xsl:when>
376
+ <xsl:otherwise>
377
+ <mroot>
378
+ <mrow>
379
+ <xsl:apply-templates select="m:e[1]"/>
380
+ </mrow>
381
+ <mrow>
382
+ <xsl:apply-templates select="m:deg[1]"/>
383
+ </mrow>
384
+ </mroot>
385
+ </xsl:otherwise>
386
+ </xsl:choose>
387
+ </xsl:template>
388
+
389
+ <!-- %%Template match m:nary
390
+ Process an n-ary.
391
+
392
+ Decides, based on which arguments are supplied, between
393
+ using an mo, msup, msub, or msubsup for the n-ary operator
394
+ -->
395
+ <xsl:template match="m:nary">
396
+ <xsl:variable name="sLowerCaseSubHide">
397
+ <xsl:choose>
398
+ <xsl:when test="count(m:naryPr[last()]/m:subHide) = 0">
399
+ <xsl:text>off</xsl:text>
400
+ </xsl:when>
401
+ <xsl:otherwise>
402
+ <xsl:value-of select="translate(m:naryPr[last()]/m:subHide/@m:val, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
403
+ </xsl:otherwise>
404
+ </xsl:choose>
405
+ </xsl:variable>
406
+ <xsl:variable name="sLowerCaseSupHide">
407
+ <xsl:choose>
408
+ <xsl:when test="count(m:naryPr[last()]/m:supHide) = 0">
409
+ <xsl:text>off</xsl:text>
410
+ </xsl:when>
411
+ <xsl:otherwise>
412
+ <xsl:value-of select="translate(m:naryPr[last()]/m:supHide/@m:val, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
413
+ </xsl:otherwise>
414
+ </xsl:choose>
415
+ </xsl:variable>
416
+ <xsl:variable name="sLowerCaseLimLoc">
417
+ <xsl:value-of select="translate(m:naryPr[last()]/m:limLoc/@m:val, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
418
+ </xsl:variable>
419
+ <xsl:variable name="fLimLocSubSup">
420
+ <xsl:choose>
421
+ <xsl:when test="count(m:naryPr[last()]/m:limLoc)=0 or $sLowerCaseLimLoc='subsup'">1</xsl:when>
422
+ <xsl:otherwise>0</xsl:otherwise>
423
+ </xsl:choose>
424
+ </xsl:variable>
425
+ <xsl:choose>
426
+ <xsl:when test="not($sLowerCaseSupHide='off') and not($sLowerCaseSubHide='off')">
427
+ <mo>
428
+ <xsl:choose>
429
+ <xsl:when test="not(m:naryPr[last()]/m:chr/@m:val) or m:naryPr[last()]/m:chr/@m:val=''">
430
+ <xsl:text>&#x222b;</xsl:text>
431
+ </xsl:when>
432
+ <xsl:otherwise>
433
+ <xsl:value-of select="m:naryPr[last()]/m:chr/@m:val"/>
434
+ </xsl:otherwise>
435
+ </xsl:choose>
436
+ </mo>
437
+ </xsl:when>
438
+ <xsl:when test="not($sLowerCaseSubHide='off')">
439
+ <xsl:choose>
440
+ <xsl:when test="$fLimLocSubSup=1">
441
+ <msup>
442
+ <mo>
443
+ <xsl:choose>
444
+ <xsl:when test="not(m:naryPr[last()]/m:chr/@m:val) or m:naryPr[last()]/m:chr/@m:val=''">
445
+ <xsl:text>&#x222b;</xsl:text>
446
+ </xsl:when>
447
+ <xsl:otherwise>
448
+ <xsl:value-of select="m:naryPr[last()]/m:chr/@m:val"/>
449
+ </xsl:otherwise>
450
+ </xsl:choose>
451
+ </mo>
452
+ <mrow>
453
+ <xsl:apply-templates select="m:sup[1]"/>
454
+ </mrow>
455
+ </msup>
456
+ </xsl:when>
457
+ <xsl:otherwise>
458
+ <mover>
459
+ <mo>
460
+ <xsl:choose>
461
+ <xsl:when test="not(m:naryPr[last()]/m:chr/@m:val) or m:naryPr[last()]/m:chr/@m:val=''">
462
+ <xsl:text>&#x222b;</xsl:text>
463
+ </xsl:when>
464
+ <xsl:otherwise>
465
+ <xsl:value-of select="m:naryPr[last()]/m:chr/@m:val"/>
466
+ </xsl:otherwise>
467
+ </xsl:choose>
468
+ </mo>
469
+ <mrow>
470
+ <xsl:apply-templates select="m:sup[1]"/>
471
+ </mrow>
472
+ </mover>
473
+ </xsl:otherwise>
474
+ </xsl:choose>
475
+ </xsl:when>
476
+ <xsl:when test="not($sLowerCaseSupHide='off')">
477
+ <xsl:choose>
478
+ <xsl:when test="$fLimLocSubSup=1">
479
+ <msub>
480
+ <mo>
481
+ <xsl:choose>
482
+ <xsl:when test="not(m:naryPr[last()]/m:chr/@m:val) or m:naryPr[last()]/m:chr/@m:val=''">
483
+ <xsl:text>&#x222b;</xsl:text>
484
+ </xsl:when>
485
+ <xsl:otherwise>
486
+ <xsl:value-of select="m:naryPr[last()]/m:chr/@m:val"/>
487
+ </xsl:otherwise>
488
+ </xsl:choose>
489
+ </mo>
490
+ <mrow>
491
+ <xsl:apply-templates select="m:sub[1]"/>
492
+ </mrow>
493
+ </msub>
494
+ </xsl:when>
495
+ <xsl:otherwise>
496
+ <munder>
497
+ <mo>
498
+ <xsl:choose>
499
+ <xsl:when test="not(m:naryPr[last()]/m:chr/@m:val) or m:naryPr[last()]/m:chr/@m:val=''">
500
+ <xsl:text>&#x222b;</xsl:text>
501
+ </xsl:when>
502
+ <xsl:otherwise>
503
+ <xsl:value-of select="m:naryPr[last()]/m:chr/@m:val"/>
504
+ </xsl:otherwise>
505
+ </xsl:choose>
506
+ </mo>
507
+ <mrow>
508
+ <xsl:apply-templates select="m:sub[1]"/>
509
+ </mrow>
510
+ </munder>
511
+ </xsl:otherwise>
512
+ </xsl:choose>
513
+ </xsl:when>
514
+ <xsl:otherwise>
515
+ <xsl:choose>
516
+ <xsl:when test="$fLimLocSubSup=1">
517
+ <msubsup>
518
+ <mo>
519
+ <xsl:choose>
520
+ <xsl:when test="not(m:naryPr[last()]/m:chr/@m:val) or m:naryPr[last()]/m:chr/@m:val=''">
521
+ <xsl:text>&#x222b;</xsl:text>
522
+ </xsl:when>
523
+ <xsl:otherwise>
524
+ <xsl:value-of select="m:naryPr[last()]/m:chr/@m:val"/>
525
+ </xsl:otherwise>
526
+ </xsl:choose>
527
+ </mo>
528
+ <mrow>
529
+ <xsl:apply-templates select="m:sub[1]"/>
530
+ </mrow>
531
+ <mrow>
532
+ <xsl:apply-templates select="m:sup[1]"/>
533
+ </mrow>
534
+ </msubsup>
535
+ </xsl:when>
536
+ <xsl:otherwise>
537
+ <munderover>
538
+ <mo>
539
+ <xsl:choose>
540
+ <xsl:when test="not(m:naryPr[last()]/m:chr/@m:val) or m:naryPr[last()]/m:chr/@m:val=''">
541
+ <xsl:text>&#x222b;</xsl:text>
542
+ </xsl:when>
543
+ <xsl:otherwise>
544
+ <xsl:value-of select="m:naryPr[last()]/m:chr/@m:val"/>
545
+ </xsl:otherwise>
546
+ </xsl:choose>
547
+ </mo>
548
+ <mrow>
549
+ <xsl:apply-templates select="m:sub[1]"/>
550
+ </mrow>
551
+ <mrow>
552
+ <xsl:apply-templates select="m:sup[1]"/>
553
+ </mrow>
554
+ </munderover>
555
+ </xsl:otherwise>
556
+ </xsl:choose>
557
+ </xsl:otherwise>
558
+ </xsl:choose>
559
+ <mrow>
560
+ <xsl:apply-templates select="m:e[1]"/>
561
+ </mrow>
562
+ </xsl:template>
563
+
564
+ <xsl:template match="m:limLow">
565
+ <munder>
566
+ <mrow>
567
+ <xsl:apply-templates select="m:e[1]"/>
568
+ </mrow>
569
+ <mrow>
570
+ <xsl:apply-templates select="m:lim[1]"/>
571
+ </mrow>
572
+ </munder>
573
+ </xsl:template>
574
+
575
+ <xsl:template match="m:limUpp">
576
+ <mover>
577
+ <mrow>
578
+ <xsl:apply-templates select="m:e[1]"/>
579
+ </mrow>
580
+ <mrow>
581
+ <xsl:apply-templates select="m:lim[1]"/>
582
+ </mrow>
583
+ </mover>
584
+ </xsl:template>
585
+
586
+ <xsl:template match="m:sSub">
587
+ <msub>
588
+ <mrow>
589
+ <xsl:apply-templates select="m:e[1]"/>
590
+ </mrow>
591
+ <mrow>
592
+ <xsl:apply-templates select="m:sub[1]"/>
593
+ </mrow>
594
+ </msub>
595
+ </xsl:template>
596
+
597
+ <xsl:template match="m:sSup">
598
+ <msup>
599
+ <mrow>
600
+ <xsl:apply-templates select="m:e[1]"/>
601
+ </mrow>
602
+ <mrow>
603
+ <xsl:apply-templates select="m:sup[1]"/>
604
+ </mrow>
605
+ </msup>
606
+ </xsl:template>
607
+
608
+ <xsl:template match="m:sSubSup">
609
+ <msubsup>
610
+ <mrow>
611
+ <xsl:apply-templates select="m:e[1]"/>
612
+ </mrow>
613
+ <mrow>
614
+ <xsl:apply-templates select="m:sub[1]"/>
615
+ </mrow>
616
+ <mrow>
617
+ <xsl:apply-templates select="m:sup[1]"/>
618
+ </mrow>
619
+ </msubsup>
620
+ </xsl:template>
621
+
622
+ <xsl:template match="m:groupChr">
623
+ <xsl:variable name="ndLastGroupChrPr" select="m:groupChrPr[last()]"/>
624
+ <xsl:variable name="sLowerCasePos"
625
+ select="translate($ndLastGroupChrPr/m:pos/@m:val, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
626
+
627
+ <xsl:variable name="sLowerCaseVertJc"
628
+ select="translate($ndLastGroupChrPr/m:vertJc/@m:val, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
629
+ <xsl:variable name="ndLastChr" select="$ndLastGroupChrPr/m:chr"/>
630
+
631
+ <xsl:variable name="chr">
632
+ <xsl:choose>
633
+ <xsl:when test="$ndLastChr and (not($ndLastChr/@m:val) or string-length($ndLastChr/@m:val) = 0)"/>
634
+ <xsl:when test="string-length($ndLastChr/@m:val) &gt;= 1">
635
+ <xsl:value-of select="substring($ndLastChr/@m:val,1,1)"/>
636
+ </xsl:when>
637
+ <xsl:otherwise>
638
+ <xsl:text>&amp;#x023DF;</xsl:text>
639
+ </xsl:otherwise>
640
+ </xsl:choose>
641
+ </xsl:variable>
642
+ <xsl:choose>
643
+ <xsl:when test="$sLowerCasePos = 'top'">
644
+ <xsl:choose>
645
+ <xsl:when test="$sLowerCaseVertJc = 'bot'">
646
+ <mover accent="false">
647
+ <mrow>
648
+ <xsl:apply-templates select="m:e[1]"/>
649
+ </mrow>
650
+ <mo>
651
+ <xsl:value-of disable-output-escaping="yes" select="$chr"/>
652
+ </mo>
653
+ </mover>
654
+ </xsl:when>
655
+ <xsl:otherwise>
656
+ <munder accentunder="false">
657
+ <mo>
658
+ <xsl:value-of disable-output-escaping="yes" select="$chr"/>
659
+ </mo>
660
+ <mrow>
661
+ <xsl:apply-templates select="m:e[1]"/>
662
+ </mrow>
663
+ </munder>
664
+ </xsl:otherwise>
665
+ </xsl:choose>
666
+ </xsl:when>
667
+ <xsl:otherwise>
668
+ <xsl:choose>
669
+ <xsl:when test="$sLowerCaseVertJc = 'bot'">
670
+ <mover accent="false">
671
+ <mo>
672
+ <xsl:value-of disable-output-escaping="yes" select="$chr"/>
673
+ </mo>
674
+ <mrow>
675
+ <xsl:apply-templates select="m:e[1]"/>
676
+ </mrow>
677
+ </mover>
678
+ </xsl:when>
679
+ <xsl:otherwise>
680
+ <munder accentunder="false">
681
+ <mrow>
682
+ <xsl:apply-templates select="m:e[1]"/>
683
+ </mrow>
684
+ <mo>
685
+ <xsl:value-of disable-output-escaping="yes" select="$chr"/>
686
+ </mo>
687
+ </munder>
688
+ </xsl:otherwise>
689
+ </xsl:choose>
690
+ </xsl:otherwise>
691
+ </xsl:choose>
692
+ </xsl:template>
693
+
694
+ <xsl:template name="fName">
695
+ <xsl:for-each select="m:fName/*">
696
+ <xsl:apply-templates select="."/>
697
+ </xsl:for-each>
698
+ </xsl:template>
699
+
700
+ <xsl:template match="m:func">
701
+ <mrow>
702
+ <mrow>
703
+ <xsl:call-template name="fName"/>
704
+ </mrow>
705
+ <mo>⁡</mo>
706
+ <mrow>
707
+ <xsl:apply-templates select="m:e"/>
708
+ </mrow>
709
+ </mrow>
710
+ </xsl:template>
711
+
712
+ <!-- %%Template: match m:f
713
+
714
+ m:f maps directly to mfrac.
715
+ -->
716
+ <xsl:template match="m:f">
717
+ <xsl:variable name="sLowerCaseType"
718
+ select="translate(m:fPr[last()]/m:type/@m:val, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
719
+ <xsl:choose>
720
+ <xsl:when test="$sLowerCaseType='lin'">
721
+ <mrow>
722
+ <mrow>
723
+ <xsl:apply-templates select="m:num[1]"/>
724
+ </mrow>
725
+ <mo>/</mo>
726
+ <mrow>
727
+ <xsl:apply-templates select="m:den[1]"/>
728
+ </mrow>
729
+ </mrow>
730
+ </xsl:when>
731
+ <xsl:otherwise>
732
+ <mfrac>
733
+ <xsl:call-template name="CreateMathMLFracProp">
734
+ <xsl:with-param name="type" select="$sLowerCaseType"/>
735
+ </xsl:call-template>
736
+ <mrow>
737
+ <xsl:apply-templates select="m:num[1]"/>
738
+ </mrow>
739
+ <mrow>
740
+ <xsl:apply-templates select="m:den[1]"/>
741
+ </mrow>
742
+ </mfrac>
743
+ </xsl:otherwise>
744
+ </xsl:choose>
745
+
746
+ </xsl:template>
747
+
748
+
749
+ <!-- %%Template: CreateMathMLFracProp
750
+
751
+ Make fraction properties based on supplied parameters.
752
+ OMML differentiates between a linear fraction and a skewed
753
+ one. For MathML, we write both as bevelled.
754
+ -->
755
+ <xsl:template name="CreateMathMLFracProp">
756
+ <xsl:param name="type"/>
757
+ <xsl:variable name="sLowerCaseType"
758
+ select="translate($type, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
759
+
760
+ <xsl:if test="$sLowerCaseType='skw' or $sLowerCaseType='lin'">
761
+ <xsl:attribute name="bevelled">true</xsl:attribute>
762
+ </xsl:if>
763
+ <xsl:if test="$sLowerCaseType='nobar'">
764
+ <xsl:attribute name="linethickness">0pt</xsl:attribute>
765
+ </xsl:if>
766
+ <xsl:choose>
767
+ <xsl:when test="sLowerCaseNumJc='right'">
768
+ <xsl:attribute name="numalign">right</xsl:attribute>
769
+ </xsl:when>
770
+ <xsl:when test="sLowerCaseNumJc='left'">
771
+ <xsl:attribute name="numalign">left</xsl:attribute>
772
+ </xsl:when>
773
+ </xsl:choose>
774
+ <xsl:choose>
775
+ <xsl:when test="sLowerCaseDenJc='right'">
776
+ <xsl:attribute name="numalign">right</xsl:attribute>
777
+ </xsl:when>
778
+ <xsl:when test="sLowerCaseDenJc='left'">
779
+ <xsl:attribute name="numalign">left</xsl:attribute>
780
+ </xsl:when>
781
+ </xsl:choose>
782
+ </xsl:template>
783
+
784
+ <!-- %%Template: match m:e | m:den | m:num | m:lim | m:sup | m:sub
785
+
786
+ These element delinate parts of an expression (like the numerator). -->
787
+ <xsl:template match="m:e | m:den | m:num | m:lim | m:sup | m:sub">
788
+ <xsl:choose>
789
+
790
+ <!-- If there is no scriptLevel specified, just call through -->
791
+ <xsl:when test="not(m:argPr[last()]/m:scrLvl/@m:val)">
792
+ <xsl:apply-templates select="*"/>
793
+ </xsl:when>
794
+
795
+ <!-- Otherwise, create an mstyle and set the script level -->
796
+ <xsl:otherwise>
797
+ <mstyle>
798
+ <xsl:attribute name="scriptlevel">
799
+ <xsl:value-of select="m:argPr[last()]/m:scrLvl/@m:val"/>
800
+ </xsl:attribute>
801
+ <xsl:apply-templates select="*"/>
802
+ </mstyle>
803
+ </xsl:otherwise>
804
+ </xsl:choose>
805
+ </xsl:template>
806
+
807
+ <xsl:template match="m:bar">
808
+ <xsl:variable name="sLowerCasePos"
809
+ select="translate(m:barPr/m:pos/@m:val, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
810
+
811
+ <xsl:variable name="fTop">
812
+
813
+ <xsl:choose>
814
+ <xsl:when test="$sLowerCasePos='top'">1</xsl:when>
815
+ <xsl:otherwise>0</xsl:otherwise>
816
+ </xsl:choose>
817
+ </xsl:variable>
818
+ <xsl:choose>
819
+ <xsl:when test="$fTop=1">
820
+ <mover>
821
+ <mrow>
822
+ <xsl:apply-templates select="m:e[1]"/>
823
+ </mrow>
824
+ <mo>
825
+ <xsl:text>&#x000AF;</xsl:text>
826
+ </mo>
827
+ </mover>
828
+ </xsl:when>
829
+ <xsl:otherwise>
830
+ <munder>
831
+ <mrow>
832
+ <xsl:apply-templates select="m:e[1]"/>
833
+ </mrow>
834
+ <mo>
835
+ <xsl:text>&#x00332;</xsl:text>
836
+ </mo>
837
+ </munder>
838
+ </xsl:otherwise>
839
+ </xsl:choose>
840
+ </xsl:template>
841
+
842
+ <!-- %%Template match m:d
843
+
844
+ Process a delimiter.
845
+ -->
846
+ <xsl:template match="m:d">
847
+ <mfenced>
848
+ <!-- open: default is '(' for both OMML and MathML -->
849
+ <xsl:if test="m:dPr[1]/m:begChr/@m:val and not(m:dPr[1]/m:begChr/@m:val ='(')">
850
+ <xsl:attribute name="open">
851
+ <xsl:value-of select="m:dPr[1]/m:begChr/@m:val"/>
852
+ </xsl:attribute>
853
+ </xsl:if>
854
+
855
+ <!-- close: default is ')' for both OMML and MathML -->
856
+ <xsl:if test="m:dPr[1]/m:endChr/@m:val and not(m:dPr[1]/m:endChr/@m:val =')')">
857
+ <xsl:attribute name="close">
858
+ <xsl:value-of select="m:dPr[1]/m:endChr/@m:val"/>
859
+ </xsl:attribute>
860
+ </xsl:if>
861
+
862
+ <!-- separator: the default is ',' for MathML, and '|' for OMML -->
863
+ <xsl:choose>
864
+ <!-- Matches MathML default. Write nothing -->
865
+ <xsl:when test="m:dPr[1]/m:sepChr/@m:val = ','"/>
866
+
867
+ <!-- OMML default: | -->
868
+ <xsl:when test="not(m:dPr[1]/m:sepChr/@m:val)">
869
+ <xsl:attribute name="separators">
870
+ <xsl:value-of select="'|'"/>
871
+ </xsl:attribute>
872
+ </xsl:when>
873
+
874
+ <xsl:otherwise>
875
+ <xsl:attribute name="separators">
876
+ <xsl:value-of select="m:dPr[1]/m:sepChr/@m:val"/>
877
+ </xsl:attribute>
878
+ </xsl:otherwise>
879
+ </xsl:choose>
880
+
881
+ <!-- now write all the children. Put each one into an mrow
882
+ just in case it produces multiple runs, etc -->
883
+ <xsl:for-each select="m:e">
884
+ <mrow>
885
+ <xsl:apply-templates select="."/>
886
+ </mrow>
887
+ </xsl:for-each>
888
+ </mfenced>
889
+ </xsl:template>
890
+
891
+ <xsl:template match="m:r">
892
+ <xsl:variable name="sLowerCaseNor"
893
+ select="translate(child::m:rPr[last()]/m:nor/@m:val, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
894
+ <xsl:variable name="sLowerCaseLit"
895
+ select="translate(child::m:rPr[child::m:lit][last()]/@m:val, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
896
+
897
+ <xsl:variable name="fNor">
898
+ <xsl:choose>
899
+ <xsl:when test="$sLowerCaseNor='off' or count(child::m:rPr[last()]/m:nor) = 0">0</xsl:when>
900
+ <xsl:otherwise>1</xsl:otherwise>
901
+ </xsl:choose>
902
+ </xsl:variable>
903
+ <xsl:variable name="fLit">
904
+ <xsl:choose>
905
+ <xsl:when test="not(child::m:rPr[child::m:lit][last()]) or $sLowerCaseLit='off'">0</xsl:when>
906
+ <xsl:otherwise>1</xsl:otherwise>
907
+ </xsl:choose>
908
+ </xsl:variable>
909
+
910
+ <xsl:choose>
911
+ <xsl:when test="$fNor=1">
912
+ <xsl:choose>
913
+ <xsl:when test="$fLit=1">
914
+ <maction actiontype="lit">
915
+ <mtext>
916
+ <xsl:call-template name="checkDirectFormatting"/>
917
+ <xsl:value-of select=".//m:t"/>
918
+ </mtext>
919
+ </maction>
920
+ </xsl:when>
921
+ <xsl:otherwise>
922
+ <mtext>
923
+ <xsl:call-template name="checkDirectFormatting"/>
924
+ <xsl:value-of select=".//m:t"/>
925
+ </mtext>
926
+ </xsl:otherwise>
927
+ </xsl:choose>
928
+ </xsl:when>
929
+ <xsl:otherwise>
930
+ <xsl:choose>
931
+ <xsl:when test="$fLit=1">
932
+ <maction actiontype="lit">
933
+ <xsl:for-each select=".//m:t">
934
+ <xsl:call-template name="ParseMt">
935
+ <xsl:with-param name="sToParse" select="text()"/>
936
+ <xsl:with-param name="scr" select="../m:rPr[last()]/m:scr/@m:val"/>
937
+ <xsl:with-param name="sty" select="../m:rPr[last()]/m:sty/@m:val"/>
938
+ <xsl:with-param name="nor" select="../m:rPr[last()]/m:nor/@m:val"/>
939
+ </xsl:call-template>
940
+ </xsl:for-each>
941
+ </maction>
942
+ </xsl:when>
943
+ <xsl:otherwise>
944
+ <xsl:for-each select=".//m:t">
945
+ <xsl:call-template name="ParseMt">
946
+ <xsl:with-param name="sToParse" select="text()"/>
947
+ <xsl:with-param name="scr" select="../m:rPr[last()]/m:scr/@m:val"/>
948
+ <xsl:with-param name="sty" select="../m:rPr[last()]/m:sty/@m:val"/>
949
+ <xsl:with-param name="nor" select="../m:rPr[last()]/m:nor/@m:val"/>
950
+ </xsl:call-template>
951
+ </xsl:for-each>
952
+ </xsl:otherwise>
953
+ </xsl:choose>
954
+ </xsl:otherwise>
955
+ </xsl:choose>
956
+ </xsl:template>
957
+
958
+
959
+ <xsl:template name="CreateTokenAttributes">
960
+ <xsl:param name="scr"/>
961
+ <xsl:param name="sty"/>
962
+ <xsl:param name="nor"/>
963
+ <xsl:param name="nCharToPrint"/>
964
+ <xsl:param name="sTokenType"/>
965
+ <xsl:variable name="sLowerCaseNor"
966
+ select="translate($nor, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
967
+ <xsl:choose>
968
+ <xsl:when test="$sLowerCaseNor = 'on'">
969
+ <xsl:attribute name="mathvariant">normal</xsl:attribute>
970
+ </xsl:when>
971
+ <xsl:otherwise>
972
+ <xsl:variable name="mathvariant">
973
+ <xsl:choose>
974
+ <!-- numbers don't care -->
975
+ <xsl:when test="$sTokenType='mn'"/>
976
+
977
+ <xsl:when test="$scr='monospace'">monospace</xsl:when>
978
+ <xsl:when test="$scr='sans-serif' and $sty='i'">sans-serif-italic</xsl:when>
979
+ <xsl:when test="$scr='sans-serif' and $sty='b'">bold-sans-serif</xsl:when>
980
+ <xsl:when test="$scr='sans-serif' and $sty='bi'">sans-serif-bold-italic</xsl:when>
981
+ <xsl:when test="$scr='sans-serif'">sans-serif</xsl:when>
982
+ <xsl:when test="$scr='fraktur' and $sty='b'">bold-fraktur</xsl:when>
983
+ <xsl:when test="$scr='fraktur'">fraktur</xsl:when>
984
+ <xsl:when test="$scr='double-struck'">double-struck</xsl:when>
985
+ <xsl:when test="$scr='script' and $sty='b'">bold-script</xsl:when>
986
+ <xsl:when test="$scr='script'">script</xsl:when>
987
+ <xsl:when test="($scr='roman' or not($scr) or $scr='') and $sty='b'">bold</xsl:when>
988
+ <xsl:when test="($scr='roman' or not($scr) or $scr='') and $sty='i'">italic</xsl:when>
989
+ <xsl:when test="($scr='roman' or not($scr) or $scr='') and $sty='p'">normal</xsl:when>
990
+ <xsl:when test="($scr='roman' or not($scr) or $scr='') and $sty='bi'">bold-italic</xsl:when>
991
+ <xsl:otherwise/>
992
+ </xsl:choose>
993
+ </xsl:variable>
994
+ <xsl:variable name="fontweight">
995
+ <xsl:choose>
996
+ <xsl:when test="$sty='b' or $sty='bi'">bold</xsl:when>
997
+ <xsl:otherwise>normal</xsl:otherwise>
998
+ </xsl:choose>
999
+ </xsl:variable>
1000
+ <xsl:variable name="fontstyle">
1001
+ <xsl:choose>
1002
+ <xsl:when test="$sty='p' or $sty='b'">normal</xsl:when>
1003
+ <xsl:otherwise>italic</xsl:otherwise>
1004
+ </xsl:choose>
1005
+ </xsl:variable>
1006
+
1007
+ <!-- Writing of attributes begins here -->
1008
+ <xsl:choose>
1009
+ <!-- Don't write mathvariant for operators unless they want to be normal -->
1010
+ <xsl:when test="$sTokenType='mo' and $mathvariant!='normal'"/>
1011
+
1012
+ <!-- A single character within an mi is already italics, don't write -->
1013
+ <xsl:when test="$sTokenType='mi' and $nCharToPrint=1 and ($mathvariant='' or $mathvariant='italic')"/>
1014
+
1015
+ <xsl:when test="$sTokenType='mi' and $nCharToPrint &gt; 1 and ($mathvariant='' or $mathvariant='italic')">
1016
+ <xsl:attribute name="mathvariant">
1017
+ <xsl:value-of select="'italic'"/>
1018
+ </xsl:attribute>
1019
+ </xsl:when>
1020
+ <xsl:when test="$mathvariant!='italic' and $mathvariant!=''">
1021
+ <xsl:attribute name="mathvariant">
1022
+ <xsl:value-of select="$mathvariant"/>
1023
+ </xsl:attribute>
1024
+ </xsl:when>
1025
+ <xsl:otherwise>
1026
+ <xsl:if test="not($sTokenType='mi' and $nCharToPrint=1) and $fontstyle='italic'">
1027
+ <xsl:attribute name="fontstyle">italic</xsl:attribute>
1028
+ </xsl:if>
1029
+ <xsl:if test="$fontweight='bold'">
1030
+ <xsl:attribute name="fontweight">bold</xsl:attribute>
1031
+ </xsl:if>
1032
+ </xsl:otherwise>
1033
+ </xsl:choose>
1034
+ </xsl:otherwise>
1035
+ </xsl:choose>
1036
+ </xsl:template>
1037
+
1038
+ <xsl:template match="m:eqArr">
1039
+ <mtable>
1040
+ <xsl:for-each select="m:e">
1041
+ <mtr>
1042
+ <mtd>
1043
+ <xsl:choose>
1044
+ <xsl:when test="m:argPr[last()]/m:scrLvl/@m:val!='0' or not(m:argPr[last()]/m:scrLvl/@m:val) or m:argPr[last()]/m:scrLvl/@m:val=''">
1045
+ <mrow>
1046
+ <maligngroup/>
1047
+ <xsl:call-template name="CreateEqArrRow">
1048
+ <xsl:with-param name="align" select="1"/>
1049
+ <xsl:with-param name="ndCur" select="*[1]"/>
1050
+ </xsl:call-template>
1051
+ </mrow>
1052
+ </xsl:when>
1053
+ <xsl:otherwise>
1054
+ <mstyle>
1055
+ <xsl:attribute name="scriptlevel">
1056
+ <xsl:value-of select="m:argPr[last()]/m:scrLvl/@m:val"/>
1057
+ </xsl:attribute>
1058
+ <maligngroup/>
1059
+ <xsl:call-template name="CreateEqArrRow">
1060
+ <xsl:with-param name="align" select="1"/>
1061
+ <xsl:with-param name="ndCur" select="*[1]"/>
1062
+ </xsl:call-template>
1063
+ </mstyle>
1064
+ </xsl:otherwise>
1065
+ </xsl:choose>
1066
+ </mtd>
1067
+ </mtr>
1068
+ </xsl:for-each>
1069
+ </mtable>
1070
+ </xsl:template>
1071
+
1072
+ <xsl:template name="CreateEqArrRow">
1073
+ <xsl:param name="align"/>
1074
+ <xsl:param name="ndCur"/>
1075
+ <xsl:variable name="sAllMt">
1076
+ <xsl:for-each select="$ndCur/m:t">
1077
+ <xsl:value-of select="."/>
1078
+ </xsl:for-each>
1079
+ </xsl:variable>
1080
+ <xsl:choose>
1081
+ <xsl:when test="$ndCur/self::m:r">
1082
+ <xsl:call-template name="ParseEqArrMr">
1083
+ <xsl:with-param name="sToParse" select="$sAllMt"/>
1084
+ <xsl:with-param name="scr" select="../m:rPr[last()]/m:scr/@m:val"/>
1085
+ <xsl:with-param name="sty" select="../m:rPr[last()]/m:sty/@m:val"/>
1086
+ <xsl:with-param name="nor" select="../m:rPr[last()]/m:nor/@m:val"/>
1087
+ <xsl:with-param name="align" select="$align"/>
1088
+ </xsl:call-template>
1089
+ </xsl:when>
1090
+ <xsl:otherwise>
1091
+ <xsl:apply-templates select="$ndCur"/>
1092
+ </xsl:otherwise>
1093
+ </xsl:choose>
1094
+ <xsl:if test="count($ndCur/following-sibling::*) &gt; 0">
1095
+ <xsl:variable name="cAmp">
1096
+ <xsl:call-template name="CountAmp">
1097
+ <xsl:with-param name="sAllMt" select="$sAllMt"/>
1098
+ <xsl:with-param name="cAmp" select="0"/>
1099
+ </xsl:call-template>
1100
+ </xsl:variable>
1101
+ <xsl:call-template name="CreateEqArrRow">
1102
+ <xsl:with-param name="align" select="($align+($cAmp mod 2)) mod 2"/>
1103
+ <xsl:with-param name="ndCur" select="$ndCur/following-sibling::*[1]"/>
1104
+ </xsl:call-template>
1105
+ </xsl:if>
1106
+ </xsl:template>
1107
+
1108
+ <xsl:template name="CountAmp">
1109
+ <xsl:param name="sAllMt"/>
1110
+ <xsl:param name="cAmp"/>
1111
+ <xsl:choose>
1112
+ <xsl:when test="string-length(substring-after($sAllMt, '&amp;')) &gt; 0 or substring($sAllMt, string-length($sAllMt))='&amp;'">
1113
+ <xsl:call-template name="CountAmp">
1114
+ <xsl:with-param name="sAllMt" select="substring-after($sAllMt, '&amp;')"/>
1115
+ <xsl:with-param name="cAmp" select="$cAmp+1"/>
1116
+ </xsl:call-template>
1117
+ </xsl:when>
1118
+ <xsl:otherwise>
1119
+ <xsl:value-of select="$cAmp"/>
1120
+ </xsl:otherwise>
1121
+ </xsl:choose>
1122
+ </xsl:template>
1123
+
1124
+ <!-- %%Template: ParseEqArrMr
1125
+
1126
+ Similar to ParseMt, but this one has to do more for an equation array.
1127
+ In equation arrays &amp; is a special character which denotes alignment.
1128
+
1129
+ The &amp; in an equation works by alternating between meaning insert alignment spacing
1130
+ and insert alignment mark. For each equation in the equation array
1131
+ there is an implied align space at the beginning of the equation. Within each equation,
1132
+ the first &amp; means alignmark, the second, align space, the third, alignmark, etc.
1133
+
1134
+ For this reason when parsing m:r's in equation arrays it is important to keep track of what
1135
+ the next ampersand will mean.
1136
+
1137
+ $align=0 => Omml's align space, which is similar to MathML's maligngroup.
1138
+ $align=1 => Omml's alignment mark, which is similar to MathML's malignmark.
1139
+ -->
1140
+ <xsl:template name="ParseEqArrMr">
1141
+ <xsl:param name="sToParse"/>
1142
+ <xsl:param name="sty"/>
1143
+ <xsl:param name="scr"/>
1144
+ <xsl:param name="nor"/>
1145
+ <xsl:param name="align"/>
1146
+
1147
+ <xsl:if test="string-length($sToParse) &gt; 0">
1148
+ <xsl:choose>
1149
+ <xsl:when test="substring($sToParse,1,1) = '&amp;'">
1150
+ <xsl:choose>
1151
+ <xsl:when test="$align=0">
1152
+ <maligngroup/>
1153
+ </xsl:when>
1154
+ <xsl:when test="$align=1">
1155
+ <malignmark/>
1156
+ </xsl:when>
1157
+ </xsl:choose>
1158
+ <xsl:call-template name="ParseEqArrMr">
1159
+ <xsl:with-param name="sToParse" select="substring($sToParse,2)"/>
1160
+ <xsl:with-param name="scr" select="$scr"/>
1161
+ <xsl:with-param name="sty" select="$sty"/>
1162
+ <xsl:with-param name="nor" select="$nor"/>
1163
+ <xsl:with-param name="align">
1164
+ <xsl:choose>
1165
+ <xsl:when test="$align=1">0</xsl:when>
1166
+ <xsl:otherwise>1</xsl:otherwise>
1167
+ </xsl:choose>
1168
+ </xsl:with-param>
1169
+ </xsl:call-template>
1170
+ </xsl:when>
1171
+ <xsl:otherwise>
1172
+ <xsl:variable name="sRepNumWith0">
1173
+ <xsl:call-template name="SReplaceNumWithZero">
1174
+ <xsl:with-param name="sToParse" select="$sToParse"/>
1175
+ </xsl:call-template>
1176
+ </xsl:variable>
1177
+ <xsl:variable name="sRepOperWith-">
1178
+ <xsl:call-template name="SReplaceOperWithMinus">
1179
+ <xsl:with-param name="sToParse" select="$sRepNumWith0"/>
1180
+ </xsl:call-template>
1181
+ </xsl:variable>
1182
+
1183
+ <xsl:variable name="iFirstOper"
1184
+ select="string-length($sRepOperWith-) - string-length(substring-after($sRepOperWith-, '-'))"/>
1185
+ <xsl:variable name="iFirstNum"
1186
+ select="string-length($sRepOperWith-) - string-length(substring-after($sRepOperWith-, '0'))"/>
1187
+ <xsl:variable name="iFirstAmp"
1188
+ select="string-length($sRepOperWith-) - string-length(substring-after($sRepOperWith-, '&amp;'))"/>
1189
+ <xsl:variable name="fNumAtPos1">
1190
+ <xsl:choose>
1191
+ <xsl:when test="substring($sRepOperWith-,1,1)='0'">1</xsl:when>
1192
+ <xsl:otherwise>0</xsl:otherwise>
1193
+ </xsl:choose>
1194
+ </xsl:variable>
1195
+ <xsl:variable name="fOperAtPos1">
1196
+ <xsl:choose>
1197
+ <xsl:when test="substring($sRepOperWith-,1,1)='-'">1</xsl:when>
1198
+ <xsl:otherwise>0</xsl:otherwise>
1199
+ </xsl:choose>
1200
+ </xsl:variable>
1201
+ <xsl:choose>
1202
+
1203
+ <!-- Case I: The string begins with neither a number, nor an operator -->
1204
+ <xsl:when test="$fNumAtPos1='0' and $fOperAtPos1='0'">
1205
+ <mi>
1206
+ <xsl:call-template name="CreateTokenAttributes">
1207
+ <xsl:with-param name="scr" select="$scr"/>
1208
+ <xsl:with-param name="sty" select="$sty"/>
1209
+ <xsl:with-param name="nor" select="$nor"/>
1210
+ <xsl:with-param name="nCharToPrint" select="1"/>
1211
+ <xsl:with-param name="sTokenType" select="'mi'"/>
1212
+ </xsl:call-template>
1213
+ <xsl:value-of select="substring($sToParse,1,1)"/>
1214
+ </mi>
1215
+ <xsl:call-template name="ParseEqArrMr">
1216
+ <xsl:with-param name="sToParse" select="substring($sToParse, 2)"/>
1217
+ <xsl:with-param name="scr" select="$scr"/>
1218
+ <xsl:with-param name="sty" select="$sty"/>
1219
+ <xsl:with-param name="nor" select="$nor"/>
1220
+ <xsl:with-param name="align" select="$align"/>
1221
+ </xsl:call-template>
1222
+ </xsl:when>
1223
+
1224
+ <!-- Case II: There is an operator at position 1 -->
1225
+ <xsl:when test="$fOperAtPos1='1'">
1226
+ <mo>
1227
+ <xsl:call-template name="CreateTokenAttributes">
1228
+ <xsl:with-param name="scr"/>
1229
+ <xsl:with-param name="sty"/>
1230
+ <xsl:with-param name="nor" select="$nor"/>
1231
+ <xsl:with-param name="sTokenType" select="'mo'"/>
1232
+ </xsl:call-template>
1233
+ <xsl:value-of select="substring($sToParse,1,1)"/>
1234
+ </mo>
1235
+ <xsl:call-template name="ParseEqArrMr">
1236
+ <xsl:with-param name="sToParse" select="substring($sToParse, 2)"/>
1237
+ <xsl:with-param name="scr" select="$scr"/>
1238
+ <xsl:with-param name="sty" select="$sty"/>
1239
+ <xsl:with-param name="nor" select="$nor"/>
1240
+ <xsl:with-param name="align" select="$align"/>
1241
+ </xsl:call-template>
1242
+ </xsl:when>
1243
+
1244
+ <!-- Case III: There is a number at position 1 -->
1245
+ <xsl:otherwise>
1246
+ <xsl:variable name="sConsecNum">
1247
+ <xsl:call-template name="SNumStart">
1248
+ <xsl:with-param name="sToParse" select="$sToParse"/>
1249
+ <xsl:with-param name="sPattern" select="$sRepNumWith0"/>
1250
+ </xsl:call-template>
1251
+ </xsl:variable>
1252
+ <mn>
1253
+ <xsl:call-template name="CreateTokenAttributes">
1254
+ <xsl:with-param name="scr"/>
1255
+ <xsl:with-param name="sty" select="'p'"/>
1256
+ <xsl:with-param name="nor" select="$nor"/>
1257
+ <xsl:with-param name="sTokenType" select="'mn'"/>
1258
+ </xsl:call-template>
1259
+ <xsl:value-of select="$sConsecNum"/>
1260
+ </mn>
1261
+ <xsl:call-template name="ParseEqArrMr">
1262
+ <xsl:with-param name="sToParse" select="substring-after($sToParse, $sConsecNum)"/>
1263
+ <xsl:with-param name="scr" select="$scr"/>
1264
+ <xsl:with-param name="sty" select="$sty"/>
1265
+ <xsl:with-param name="nor" select="$nor"/>
1266
+ <xsl:with-param name="align" select="$align"/>
1267
+ </xsl:call-template>
1268
+ </xsl:otherwise>
1269
+ </xsl:choose>
1270
+ </xsl:otherwise>
1271
+ </xsl:choose>
1272
+ </xsl:if>
1273
+ </xsl:template>
1274
+
1275
+ <!-- %%Template: ParseMt
1276
+
1277
+ Produce a run of text. Technically, OMML makes no distinction
1278
+ between numbers, operators, and other characters in a run. For
1279
+ MathML we need to break these into mi, mn, or mo elements.
1280
+
1281
+ See also ParseEqArrMr
1282
+ -->
1283
+ <xsl:template name="ParseMt">
1284
+ <xsl:param name="sToParse"/>
1285
+ <xsl:param name="sty"/>
1286
+ <xsl:param name="scr"/>
1287
+ <xsl:param name="nor"/>
1288
+ <xsl:if test="string-length($sToParse) &gt; 0">
1289
+ <xsl:variable name="sRepNumWith0">
1290
+ <xsl:call-template name="SReplaceNumWithZero">
1291
+ <xsl:with-param name="sToParse" select="$sToParse"/>
1292
+ </xsl:call-template>
1293
+ </xsl:variable>
1294
+ <xsl:variable name="sRepOperWith-">
1295
+ <xsl:call-template name="SReplaceOperWithMinus">
1296
+ <xsl:with-param name="sToParse" select="$sRepNumWith0"/>
1297
+ </xsl:call-template>
1298
+ </xsl:variable>
1299
+
1300
+ <xsl:variable name="iFirstOper"
1301
+ select="string-length($sRepOperWith-) - string-length(substring-after($sRepOperWith-, '-'))"/>
1302
+ <xsl:variable name="iFirstNum"
1303
+ select="string-length($sRepOperWith-) - string-length(substring-after($sRepOperWith-, '0'))"/>
1304
+ <xsl:variable name="fNumAtPos1">
1305
+ <xsl:choose>
1306
+ <xsl:when test="substring($sRepOperWith-,1,1)='0'">1</xsl:when>
1307
+ <xsl:otherwise>0</xsl:otherwise>
1308
+ </xsl:choose>
1309
+ </xsl:variable>
1310
+ <xsl:variable name="fOperAtPos1">
1311
+ <xsl:choose>
1312
+ <xsl:when test="substring($sRepOperWith-,1,1)='-'">1</xsl:when>
1313
+ <xsl:otherwise>0</xsl:otherwise>
1314
+ </xsl:choose>
1315
+ </xsl:variable>
1316
+
1317
+ <xsl:choose>
1318
+
1319
+ <!-- Case I: The string begins with neither a number, nor an operator -->
1320
+ <xsl:when test="$fOperAtPos1='0' and $fNumAtPos1='0'">
1321
+ <xsl:variable name="nCharToPrint">
1322
+ <xsl:choose>
1323
+ <xsl:when test="ancestor::m:fName">
1324
+ <xsl:choose>
1325
+ <xsl:when test="($iFirstOper=$iFirstNum) and ($iFirstOper=string-length($sToParse)) and (substring($sRepOperWith-, string-length($sRepOperWith-))!='0') and (substring($sRepOperWith-, string-length($sRepOperWith-))!='-')">
1326
+ <xsl:value-of select="string-length($sToParse)"/>
1327
+ </xsl:when>
1328
+ <xsl:when test="$iFirstOper &lt; $iFirstNum">
1329
+ <xsl:value-of select="$iFirstOper - 1"/>
1330
+ </xsl:when>
1331
+ <xsl:otherwise>
1332
+ <xsl:value-of select="$iFirstNum - 1"/>
1333
+ </xsl:otherwise>
1334
+ </xsl:choose>
1335
+ </xsl:when>
1336
+ <xsl:otherwise>1</xsl:otherwise>
1337
+ </xsl:choose>
1338
+ </xsl:variable>
1339
+
1340
+ <mi>
1341
+ <xsl:call-template name="CreateTokenAttributes">
1342
+ <xsl:with-param name="scr" select="$scr"/>
1343
+ <xsl:with-param name="sty" select="$sty"/>
1344
+ <xsl:with-param name="nor" select="$nor"/>
1345
+ <xsl:with-param name="nCharToPrint" select="$nCharToPrint"/>
1346
+ <xsl:with-param name="sTokenType" select="'mi'"/>
1347
+ </xsl:call-template>
1348
+ <xsl:value-of select="substring($sToParse, 1, $nCharToPrint)"/>
1349
+ </mi>
1350
+ <xsl:call-template name="ParseMt">
1351
+ <xsl:with-param name="sToParse" select="substring($sToParse, $nCharToPrint+1)"/>
1352
+ <xsl:with-param name="scr" select="$scr"/>
1353
+ <xsl:with-param name="sty" select="$sty"/>
1354
+ <xsl:with-param name="nor" select="$nor"/>
1355
+ </xsl:call-template>
1356
+ </xsl:when>
1357
+
1358
+ <!-- Case II: There is an operator at position 1 -->
1359
+ <xsl:when test="$fOperAtPos1='1'">
1360
+ <mo>
1361
+ <xsl:call-template name="CreateTokenAttributes">
1362
+ <xsl:with-param name="scr"/>
1363
+ <xsl:with-param name="sty"/>
1364
+ <xsl:with-param name="nor" select="$nor"/>
1365
+ <xsl:with-param name="sTokenType" select="'mo'"/>
1366
+ </xsl:call-template>
1367
+ <xsl:value-of select="substring($sToParse,1,1)"/>
1368
+ </mo>
1369
+ <xsl:call-template name="ParseMt">
1370
+ <xsl:with-param name="sToParse" select="substring($sToParse, 2)"/>
1371
+ <xsl:with-param name="scr" select="$scr"/>
1372
+ <xsl:with-param name="sty" select="$sty"/>
1373
+ <xsl:with-param name="nor" select="$nor"/>
1374
+ </xsl:call-template>
1375
+ </xsl:when>
1376
+
1377
+ <!-- Case III: There is a number at position 1 -->
1378
+ <xsl:otherwise>
1379
+ <xsl:variable name="sConsecNum">
1380
+ <xsl:call-template name="SNumStart">
1381
+ <xsl:with-param name="sToParse" select="$sToParse"/>
1382
+ <xsl:with-param name="sPattern" select="$sRepNumWith0"/>
1383
+ </xsl:call-template>
1384
+ </xsl:variable>
1385
+ <mn>
1386
+ <xsl:call-template name="CreateTokenAttributes">
1387
+ <xsl:with-param name="scr" select="$scr"/>
1388
+ <xsl:with-param name="sty" select="'p'"/>
1389
+ <xsl:with-param name="nor" select="$nor"/>
1390
+ <xsl:with-param name="sTokenType" select="'mn'"/>
1391
+ </xsl:call-template>
1392
+ <xsl:value-of select="$sConsecNum"/>
1393
+ </mn>
1394
+ <xsl:call-template name="ParseMt">
1395
+ <xsl:with-param name="sToParse" select="substring-after($sToParse, $sConsecNum)"/>
1396
+ <xsl:with-param name="scr" select="$scr"/>
1397
+ <xsl:with-param name="sty" select="$sty"/>
1398
+ <xsl:with-param name="nor" select="$nor"/>
1399
+ </xsl:call-template>
1400
+ </xsl:otherwise>
1401
+ </xsl:choose>
1402
+ </xsl:if>
1403
+ </xsl:template>
1404
+
1405
+ <!-- %%Template: SNumStart
1406
+
1407
+ Return the longest substring of sToParse starting from the
1408
+ start of sToParse that is a number. In addition, it takes the
1409
+ pattern string, which is sToParse with all of its numbers
1410
+ replaced with a 0. sPattern should be the same length
1411
+ as sToParse
1412
+ -->
1413
+ <xsl:template name="SNumStart">
1414
+ <xsl:param name="sToParse" select="''"/>
1415
+ <!-- if we don't get anything, take the string itself -->
1416
+ <xsl:param name="sPattern" select="'$sToParse'"/>
1417
+
1418
+
1419
+ <xsl:choose>
1420
+ <!-- the pattern says this is a number, recurse with the rest -->
1421
+ <xsl:when test="substring($sPattern, 1, 1) = '0'">
1422
+ <xsl:call-template name="SNumStart">
1423
+ <xsl:with-param name="sToParse" select="$sToParse"/>
1424
+ <xsl:with-param name="sPattern" select="substring($sPattern, 2)"/>
1425
+ </xsl:call-template>
1426
+ </xsl:when>
1427
+
1428
+ <!-- the pattern says we've run out of numbers. Take as many
1429
+ characters from sToParse as we shaved off sPattern -->
1430
+ <xsl:otherwise>
1431
+ <xsl:value-of select="substring($sToParse, 1, string-length($sToParse) - string-length($sPattern))"/>
1432
+ </xsl:otherwise>
1433
+ </xsl:choose>
1434
+ </xsl:template>
1435
+
1436
+ <!-- %%Template SRepeatCharAcc
1437
+
1438
+ The core of SRepeatChar with an accumulator. The current
1439
+ string is in param $acc, and we will double and recurse,
1440
+ if we're less than half of the required length or else just
1441
+ add the right amount of characters to the accumulator and
1442
+ return
1443
+ -->
1444
+ <xsl:template name="SRepeatCharAcc">
1445
+ <xsl:param name="cchRequired" select="1"/>
1446
+ <xsl:param name="ch" select="'-'"/>
1447
+ <xsl:param name="acc" select="$ch"/>
1448
+
1449
+ <xsl:variable name="cchAcc" select="string-length($acc)"/>
1450
+ <xsl:choose>
1451
+ <xsl:when test="(2 * $cchAcc) &lt; $cchRequired">
1452
+ <xsl:call-template name="SRepeatCharAcc">
1453
+ <xsl:with-param name="cchRequired" select="$cchRequired"/>
1454
+ <xsl:with-param name="ch" select="$ch"/>
1455
+ <xsl:with-param name="acc" select="concat($acc, $acc)"/>
1456
+ </xsl:call-template>
1457
+ </xsl:when>
1458
+
1459
+ <xsl:otherwise>
1460
+ <xsl:value-of select="concat($acc, substring($acc, 1, $cchRequired - $cchAcc))"/>
1461
+ </xsl:otherwise>
1462
+ </xsl:choose>
1463
+ </xsl:template>
1464
+
1465
+
1466
+ <!-- %%Template SRepeatChar
1467
+
1468
+ Generates a string nchRequired long by repeating the given character ch
1469
+ -->
1470
+ <xsl:template name="SRepeatChar">
1471
+ <xsl:param name="cchRequired" select="1"/>
1472
+ <xsl:param name="ch" select="'-'"/>
1473
+
1474
+ <xsl:call-template name="SRepeatCharAcc">
1475
+ <xsl:with-param name="cchRequired" select="$cchRequired"/>
1476
+ <xsl:with-param name="ch" select="$ch"/>
1477
+ <xsl:with-param name="acc" select="$ch"/>
1478
+ </xsl:call-template>
1479
+ </xsl:template>
1480
+
1481
+ <!-- %%Template SReplaceOperWithMinus
1482
+
1483
+ Go through the given string and replace every instance
1484
+ of an operator with a minus '-'. This helps quickly identify
1485
+ the first instance of an operator.
1486
+ -->
1487
+ <xsl:template name="SReplaceOperWithMinus">
1488
+ <xsl:param name="sToParse" select="''"/>
1489
+
1490
+ <xsl:value-of select="translate($sToParse, $sOperators, $sMinuses)"/>
1491
+ </xsl:template>
1492
+
1493
+ <!-- %%Template SReplaceNumWithZero
1494
+
1495
+ Go through the given string and replace every instance
1496
+ of an number with a zero '0'. This helps quickly identify
1497
+ the first occurence of a number.
1498
+
1499
+ Considers the '.' and ',' part of a number iff they are sandwiched
1500
+ between two other numbers. 0.3 will be recognized as a number,
1501
+ x.3 will not be. Since these characters can also be an operator, this
1502
+ should be called before SReplaceOperWithMinus.
1503
+ -->
1504
+ <xsl:template name="SReplaceNumWithZero">
1505
+ <xsl:param name="sToParse" select="''"/>
1506
+
1507
+ <!-- First do a simple replace. Numbers will all be come 0's.
1508
+ After this point, the pattern involving the . or , that
1509
+ we are looking for will become 0.0 or 0,0 -->
1510
+ <xsl:variable name="sSimpleReplace" select="translate($sToParse, $sNumbers, $sZeros)"/>
1511
+
1512
+ <!-- And then, replace 0.0 with just 000. This means that the . will
1513
+ become part of the number -->
1514
+ <xsl:variable name="sReplacePeriod">
1515
+ <xsl:call-template name="SReplace">
1516
+ <xsl:with-param name="sInput" select="$sSimpleReplace"/>
1517
+ <xsl:with-param name="sOrig" select="'0.0'"/>
1518
+ <xsl:with-param name="sReplacement" select="'000'"/>
1519
+ </xsl:call-template>
1520
+ </xsl:variable>
1521
+
1522
+ <!-- And then, replace 0,0 with just 000. This means that the , will
1523
+ become part of the number -->
1524
+ <xsl:call-template name="SReplace">
1525
+ <xsl:with-param name="sInput" select="$sReplacePeriod"/>
1526
+ <xsl:with-param name="sOrig" select="'0,0'"/>
1527
+ <xsl:with-param name="sReplacement" select="'000'"/>
1528
+ </xsl:call-template>
1529
+ </xsl:template>
1530
+
1531
+ <!-- Template to translate Word's borderBox properties into the menclose notation attribute
1532
+ The initial call to this SHOULD NOT pass an sAttribute. Subsequent calls to
1533
+ CreateMencloseNotationAttrFromBorderBoxAttr by CreateMencloseNotationAttrFromBorderBoxAttr will
1534
+ update the sAttribute as appropriate.
1535
+
1536
+ CreateMencloseNotationAttrFromBorderBoxAttr looks at each attribute (fHideTop, fHideBot, etc.) one at a time
1537
+ in the order they are listed and passes a modified sAttribute to CreateMencloseNotationAttrFromBorderBoxAttr.
1538
+ Each successive call to CreateMencloseNotationAttrFromBorderBoxAttr knows which attribute to look at because
1539
+ the previous call should have omitted passing the attribute it just analyzed. This is why as you read lower
1540
+ and lower in the template that each call to CreateMencloseNotationAttrFromBorderBoxAttr has fewer and fewer attributes.
1541
+ -->
1542
+ <xsl:template name="CreateMencloseNotationAttrFromBorderBoxAttr">
1543
+ <xsl:param name="fHideTop"/>
1544
+ <xsl:param name="fHideBot"/>
1545
+ <xsl:param name="fHideLeft"/>
1546
+ <xsl:param name="fHideRight"/>
1547
+ <xsl:param name="fStrikeH"/>
1548
+ <xsl:param name="fStrikeV"/>
1549
+ <xsl:param name="fStrikeBLTR"/>
1550
+ <xsl:param name="fStrikeTLBR"/>
1551
+ <xsl:param name="sAttribute"/>
1552
+
1553
+ <xsl:choose>
1554
+ <xsl:when test="string-length($sAttribute) = 0">
1555
+ <xsl:choose>
1556
+ <xsl:when test="string-length($fHideTop) &gt; 0 and string-length($fHideBot) &gt; 0 and string-length($fHideLeft) &gt; 0 and string-length($fHideRight) &gt; 0">
1557
+
1558
+ <xsl:choose>
1559
+ <xsl:when test="$fHideTop = 0 and $fHideBot = 0 and $fHideLeft = 0 and $fHideRight = 0">
1560
+ <!-- We can use 'box' instead of top, bot, left, and right. Therefore,
1561
+ replace sAttribute with 'box' and begin analyzing params fStrikeH
1562
+ and below. -->
1563
+ <xsl:call-template name="CreateMencloseNotationAttrFromBorderBoxAttr">
1564
+ <xsl:with-param name="fStrikeH" select="$fStrikeH"/>
1565
+ <xsl:with-param name="fStrikeV" select="$fStrikeV"/>
1566
+ <xsl:with-param name="fStrikeBLTR" select="$fStrikeBLTR"/>
1567
+ <xsl:with-param name="fStrikeTLBR" select="$fStrikeTLBR"/>
1568
+ <xsl:with-param name="sAttribute">
1569
+ <xsl:text>box</xsl:text>
1570
+ </xsl:with-param>
1571
+ </xsl:call-template>
1572
+ </xsl:when>
1573
+ <xsl:otherwise>
1574
+ <!-- Can't use 'box', theremore, must analyze all attributes -->
1575
+ <xsl:call-template name="CreateMencloseNotationAttrFromBorderBoxAttr">
1576
+ <xsl:with-param name="fHideTop" select="$fHideTop"/>
1577
+ <xsl:with-param name="fHideBot" select="$fHideBot"/>
1578
+ <xsl:with-param name="fHideLeft" select="$fHideLeft"/>
1579
+ <xsl:with-param name="fHideRight" select="$fHideRight"/>
1580
+ <xsl:with-param name="fStrikeH" select="$fStrikeH"/>
1581
+ <xsl:with-param name="fStrikeV" select="$fStrikeV"/>
1582
+ <xsl:with-param name="fStrikeBLTR" select="$fStrikeBLTR"/>
1583
+ <xsl:with-param name="fStrikeTLBR" select="$fStrikeTLBR"/>
1584
+ <xsl:with-param name="sAttribute">
1585
+ <!-- Assume using all four (left right top bottom). Subsequent calls
1586
+ will remove the sides which aren't to be includes. -->
1587
+ <xsl:text>left right top bottom</xsl:text>
1588
+ </xsl:with-param>
1589
+ </xsl:call-template>
1590
+ </xsl:otherwise>
1591
+ </xsl:choose>
1592
+ </xsl:when>
1593
+ </xsl:choose>
1594
+ </xsl:when>
1595
+ <xsl:otherwise>
1596
+ <xsl:choose>
1597
+ <xsl:when test="string-length($fHideTop) &gt; 0">
1598
+ <xsl:choose>
1599
+ <xsl:when test="$fHideTop=1">
1600
+ <xsl:call-template name="CreateMencloseNotationAttrFromBorderBoxAttr">
1601
+ <xsl:with-param name="fHideBot" select="$fHideBot"/>
1602
+ <xsl:with-param name="fHideLeft" select="$fHideLeft"/>
1603
+ <xsl:with-param name="fHideRight" select="$fHideRight"/>
1604
+ <xsl:with-param name="fStrikeH" select="$fStrikeH"/>
1605
+ <xsl:with-param name="fStrikeV" select="$fStrikeV"/>
1606
+ <xsl:with-param name="fStrikeBLTR" select="$fStrikeBLTR"/>
1607
+ <xsl:with-param name="fStrikeTLBR" select="$fStrikeTLBR"/>
1608
+ <xsl:with-param name="sAttribute">
1609
+ <xsl:call-template name="SReplace">
1610
+ <xsl:with-param name="sInput" select="$sAttribute"/>
1611
+ <xsl:with-param name="sOrig" select="'top'"/>
1612
+ <xsl:with-param name="sReplacement" select="''"/>
1613
+ </xsl:call-template>
1614
+ </xsl:with-param>
1615
+ </xsl:call-template>
1616
+ </xsl:when>
1617
+ <xsl:otherwise>
1618
+ <xsl:call-template name="CreateMencloseNotationAttrFromBorderBoxAttr">
1619
+ <xsl:with-param name="fHideBot" select="$fHideBot"/>
1620
+ <xsl:with-param name="fHideLeft" select="$fHideLeft"/>
1621
+ <xsl:with-param name="fHideRight" select="$fHideRight"/>
1622
+ <xsl:with-param name="fStrikeH" select="$fStrikeH"/>
1623
+ <xsl:with-param name="fStrikeV" select="$fStrikeV"/>
1624
+ <xsl:with-param name="fStrikeBLTR" select="$fStrikeBLTR"/>
1625
+ <xsl:with-param name="fStrikeTLBR" select="$fStrikeTLBR"/>
1626
+ <xsl:with-param name="sAttribute" select="$sAttribute"/>
1627
+ </xsl:call-template>
1628
+ </xsl:otherwise>
1629
+ </xsl:choose>
1630
+ </xsl:when>
1631
+ <xsl:when test="string-length($fHideBot) &gt; 0">
1632
+ <xsl:choose>
1633
+ <xsl:when test="$fHideBot=1">
1634
+ <xsl:call-template name="CreateMencloseNotationAttrFromBorderBoxAttr">
1635
+ <xsl:with-param name="fHideLeft" select="$fHideLeft"/>
1636
+ <xsl:with-param name="fHideRight" select="$fHideRight"/>
1637
+ <xsl:with-param name="fStrikeH" select="$fStrikeH"/>
1638
+ <xsl:with-param name="fStrikeV" select="$fStrikeV"/>
1639
+ <xsl:with-param name="fStrikeBLTR" select="$fStrikeBLTR"/>
1640
+ <xsl:with-param name="fStrikeTLBR" select="$fStrikeTLBR"/>
1641
+ <xsl:with-param name="sAttribute">
1642
+ <xsl:call-template name="SReplace">
1643
+ <xsl:with-param name="sInput" select="$sAttribute"/>
1644
+ <xsl:with-param name="sOrig" select="'bottom'"/>
1645
+ <xsl:with-param name="sReplacement" select="''"/>
1646
+ </xsl:call-template>
1647
+ </xsl:with-param>
1648
+ </xsl:call-template>
1649
+ </xsl:when>
1650
+ <xsl:otherwise>
1651
+ <xsl:call-template name="CreateMencloseNotationAttrFromBorderBoxAttr">
1652
+ <xsl:with-param name="fHideLeft" select="$fHideLeft"/>
1653
+ <xsl:with-param name="fHideRight" select="$fHideRight"/>
1654
+ <xsl:with-param name="fStrikeH" select="$fStrikeH"/>
1655
+ <xsl:with-param name="fStrikeV" select="$fStrikeV"/>
1656
+ <xsl:with-param name="fStrikeBLTR" select="$fStrikeBLTR"/>
1657
+ <xsl:with-param name="fStrikeTLBR" select="$fStrikeTLBR"/>
1658
+ <xsl:with-param name="sAttribute" select="$sAttribute"/>
1659
+ </xsl:call-template>
1660
+ </xsl:otherwise>
1661
+ </xsl:choose>
1662
+ </xsl:when>
1663
+ <xsl:when test="string-length($fHideLeft) &gt; 0">
1664
+ <xsl:choose>
1665
+ <xsl:when test="$fHideLeft=1">
1666
+ <xsl:call-template name="CreateMencloseNotationAttrFromBorderBoxAttr">
1667
+ <xsl:with-param name="fHideRight" select="$fHideRight"/>
1668
+ <xsl:with-param name="fStrikeH" select="$fStrikeH"/>
1669
+ <xsl:with-param name="fStrikeV" select="$fStrikeV"/>
1670
+ <xsl:with-param name="fStrikeBLTR" select="$fStrikeBLTR"/>
1671
+ <xsl:with-param name="fStrikeTLBR" select="$fStrikeTLBR"/>
1672
+ <xsl:with-param name="sAttribute">
1673
+ <xsl:call-template name="SReplace">
1674
+ <xsl:with-param name="sInput" select="$sAttribute"/>
1675
+ <xsl:with-param name="sOrig" select="'left'"/>
1676
+ <xsl:with-param name="sReplacement" select="''"/>
1677
+ </xsl:call-template>
1678
+ </xsl:with-param>
1679
+ </xsl:call-template>
1680
+ </xsl:when>
1681
+ <xsl:otherwise>
1682
+ <xsl:call-template name="CreateMencloseNotationAttrFromBorderBoxAttr">
1683
+ <xsl:with-param name="fHideRight" select="$fHideRight"/>
1684
+ <xsl:with-param name="fStrikeH" select="$fStrikeH"/>
1685
+ <xsl:with-param name="fStrikeV" select="$fStrikeV"/>
1686
+ <xsl:with-param name="fStrikeBLTR" select="$fStrikeBLTR"/>
1687
+ <xsl:with-param name="fStrikeTLBR" select="$fStrikeTLBR"/>
1688
+ <xsl:with-param name="sAttribute" select="$sAttribute"/>
1689
+ </xsl:call-template>
1690
+ </xsl:otherwise>
1691
+ </xsl:choose>
1692
+ </xsl:when>
1693
+ <xsl:when test="string-length($fHideRight) &gt; 0">
1694
+ <xsl:choose>
1695
+ <xsl:when test="$fHideRight=1">
1696
+ <xsl:call-template name="CreateMencloseNotationAttrFromBorderBoxAttr">
1697
+ <xsl:with-param name="fStrikeH" select="$fStrikeH"/>
1698
+ <xsl:with-param name="fStrikeV" select="$fStrikeV"/>
1699
+ <xsl:with-param name="fStrikeBLTR" select="$fStrikeBLTR"/>
1700
+ <xsl:with-param name="fStrikeTLBR" select="$fStrikeTLBR"/>
1701
+ <xsl:with-param name="sAttribute">
1702
+ <xsl:call-template name="SReplace">
1703
+ <xsl:with-param name="sInput" select="$sAttribute"/>
1704
+ <xsl:with-param name="sOrig" select="'right'"/>
1705
+ <xsl:with-param name="sReplacement" select="''"/>
1706
+ </xsl:call-template>
1707
+ </xsl:with-param>
1708
+ </xsl:call-template>
1709
+ </xsl:when>
1710
+ <xsl:otherwise>
1711
+ <xsl:call-template name="CreateMencloseNotationAttrFromBorderBoxAttr">
1712
+ <xsl:with-param name="fStrikeH" select="$fStrikeH"/>
1713
+ <xsl:with-param name="fStrikeV" select="$fStrikeV"/>
1714
+ <xsl:with-param name="fStrikeBLTR" select="$fStrikeBLTR"/>
1715
+ <xsl:with-param name="fStrikeTLBR" select="$fStrikeTLBR"/>
1716
+ <xsl:with-param name="sAttribute" select="$sAttribute"/>
1717
+ </xsl:call-template>
1718
+ </xsl:otherwise>
1719
+ </xsl:choose>
1720
+ </xsl:when>
1721
+ <xsl:when test="string-length($fStrikeH) &gt; 0">
1722
+ <xsl:choose>
1723
+ <xsl:when test="$fStrikeH=1">
1724
+ <xsl:call-template name="CreateMencloseNotationAttrFromBorderBoxAttr">
1725
+ <xsl:with-param name="fStrikeV" select="$fStrikeV"/>
1726
+ <xsl:with-param name="fStrikeBLTR" select="$fStrikeBLTR"/>
1727
+ <xsl:with-param name="fStrikeTLBR" select="$fStrikeTLBR"/>
1728
+ <xsl:with-param name="sAttribute" select="concat($sAttribute, ' horizontalstrike')"/>
1729
+ </xsl:call-template>
1730
+ </xsl:when>
1731
+ <xsl:otherwise>
1732
+ <xsl:call-template name="CreateMencloseNotationAttrFromBorderBoxAttr">
1733
+ <xsl:with-param name="fStrikeV" select="$fStrikeV"/>
1734
+ <xsl:with-param name="fStrikeBLTR" select="$fStrikeBLTR"/>
1735
+ <xsl:with-param name="fStrikeTLBR" select="$fStrikeTLBR"/>
1736
+ <xsl:with-param name="sAttribute" select="$sAttribute"/>
1737
+ </xsl:call-template>
1738
+ </xsl:otherwise>
1739
+ </xsl:choose>
1740
+ </xsl:when>
1741
+ <xsl:when test="string-length($fStrikeV) &gt; 0">
1742
+ <xsl:choose>
1743
+ <xsl:when test="$fStrikeV=1">
1744
+ <xsl:call-template name="CreateMencloseNotationAttrFromBorderBoxAttr">
1745
+ <xsl:with-param name="fStrikeBLTR" select="$fStrikeBLTR"/>
1746
+ <xsl:with-param name="fStrikeTLBR" select="$fStrikeTLBR"/>
1747
+ <xsl:with-param name="sAttribute" select="concat($sAttribute, ' verticalstrike')"/>
1748
+ </xsl:call-template>
1749
+ </xsl:when>
1750
+ <xsl:otherwise>
1751
+ <xsl:call-template name="CreateMencloseNotationAttrFromBorderBoxAttr">
1752
+ <xsl:with-param name="fStrikeBLTR" select="$fStrikeBLTR"/>
1753
+ <xsl:with-param name="fStrikeTLBR" select="$fStrikeTLBR"/>
1754
+ <xsl:with-param name="sAttribute" select="$sAttribute"/>
1755
+ </xsl:call-template>
1756
+ </xsl:otherwise>
1757
+ </xsl:choose>
1758
+ </xsl:when>
1759
+ <xsl:when test="string-length($fStrikeBLTR) &gt; 0">
1760
+ <xsl:choose>
1761
+ <xsl:when test="$fStrikeBLTR=1">
1762
+ <xsl:call-template name="CreateMencloseNotationAttrFromBorderBoxAttr">
1763
+ <xsl:with-param name="fStrikeTLBR" select="$fStrikeTLBR"/>
1764
+ <xsl:with-param name="sAttribute" select="concat($sAttribute, ' updiagonalstrike')"/>
1765
+ </xsl:call-template>
1766
+ </xsl:when>
1767
+ <xsl:otherwise>
1768
+ <xsl:call-template name="CreateMencloseNotationAttrFromBorderBoxAttr">
1769
+ <xsl:with-param name="fStrikeTLBR" select="$fStrikeTLBR"/>
1770
+ <xsl:with-param name="sAttribute" select="$sAttribute"/>
1771
+ </xsl:call-template>
1772
+ </xsl:otherwise>
1773
+ </xsl:choose>
1774
+ </xsl:when>
1775
+ <xsl:when test="string-length($fStrikeTLBR) &gt; 0">
1776
+ <xsl:choose>
1777
+ <xsl:when test="$fStrikeTLBR=1">
1778
+ <xsl:call-template name="CreateMencloseNotationAttrFromBorderBoxAttr">
1779
+ <xsl:with-param name="sAttribute" select="concat($sAttribute, ' downdiagonalstrike')"/>
1780
+ </xsl:call-template>
1781
+ </xsl:when>
1782
+ <xsl:otherwise>
1783
+ <xsl:call-template name="CreateMencloseNotationAttrFromBorderBoxAttr">
1784
+ <xsl:with-param name="sAttribute" select="$sAttribute"/>
1785
+ </xsl:call-template>
1786
+ </xsl:otherwise>
1787
+ </xsl:choose>
1788
+ </xsl:when>
1789
+ <xsl:otherwise>
1790
+ <xsl:attribute name="notation">
1791
+ <xsl:value-of select="normalize-space($sAttribute)"/>
1792
+ </xsl:attribute>
1793
+ </xsl:otherwise>
1794
+ </xsl:choose>
1795
+ </xsl:otherwise>
1796
+ </xsl:choose>
1797
+ </xsl:template>
1798
+
1799
+
1800
+ <xsl:template name="checkDirectFormatting">
1801
+ <xsl:if test="w:rPr/w:rFonts/@w:ascii and not(w:rPr/w:rFonts/@w:ascii='Cambria Math')">
1802
+ <xsl:attribute name="fontfamily" select="w:rPr/w:rFonts/@w:ascii"/>
1803
+ </xsl:if>
1804
+ <xsl:choose>
1805
+ <xsl:when test="w:rPr/w:b[not(@w:val='0')]">
1806
+ <xsl:attribute name="fontweight">bold</xsl:attribute>
1807
+ </xsl:when>
1808
+ <xsl:when test="w:rPr/w:b[@w:val='0']">
1809
+ <xsl:attribute name="fontweight">normal</xsl:attribute>
1810
+ </xsl:when>
1811
+ </xsl:choose>
1812
+ <xsl:choose>
1813
+ <xsl:when test="w:rPr/w:i[not(@w:val='0')]">
1814
+ <xsl:attribute name="fontstyle">italic</xsl:attribute>
1815
+ </xsl:when>
1816
+ <xsl:when test="w:rPr/w:i[@w:val='0']">
1817
+ <xsl:attribute name="fontstyle">upright</xsl:attribute>
1818
+ </xsl:when>
1819
+ </xsl:choose>
1820
+ </xsl:template>
1821
+ </xsl:stylesheet>