html2doc 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ # This project follows the Ribose OSS style guide.
2
+ # https://github.com/riboseinc/oss-guides
3
+ # All project-specific additions and overrides should be specified in this file.
4
+
5
+ inherit_from:
6
+ # Thoughtbot's style guide from: https://github.com/thoughtbot/guides
7
+ - ".rubocop.tb.yml"
8
+ # Overrides from Ribose
9
+ - ".rubocop.ribose.yml"
10
+ AllCops:
11
+ DisplayCopNames: false
12
+ StyleGuideCopsOnly: false
13
+ TargetRubyVersion: 2.4
14
+ Rails:
15
+ Enabled: true
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.3
5
+ before_install: gem install bundler -v 1.16.1
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at ronald.tse@ribose.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in html2doc.gemspec
6
+ gemspec
@@ -0,0 +1,44 @@
1
+ = Html2Doc
2
+
3
+ Gem to convert an HTML document into a Word document (.doc) format. This is intended for automated generation of Microsoft Word documents, given HTML documents, which are mmuch more readily crafted.
4
+
5
+ This gem originated out of https://github.com/riboseinc/asciidoctor-iso, which creates a Word document from a Microsoft HTML document (created in turn by processing Asciidoc). The Microsoft HTML document is already quite close to Microsoft Word requirements, but future iterations of this gem will become more generic.
6
+
7
+ This work is driven by the Word document generation procedure documented in http://sebsauvage.net/wiki/doku.php?id=word_document_generation
8
+
9
+ The gem currently does the following:
10
+
11
+ * Resize any images in the HTML file to fit within the maximum page size. (Word will otherwise crash on reading the document.)
12
+ * Generate a filelist.xml listing of all files to be bundled into the Word document.
13
+ * Inject Microsoft Word-specific CSS into the HTML document. The CSS file used is at `lib/html2doc/wordstyle.css`, and can be customised. (This generic CSS can be overridden by CSS already in the HTML document, since the generic CSS is injected at the top of the document.)
14
+ * Bundle up the images, the HTML file of the document proper, and the `header.html` file representing header/footer information, into a MIME file, and save that file to disk (so that Microsoft Word can deal with it as a Word file.)
15
+
16
+ Future iterations will convert generic HTML to Microsoft-specific HTML. For a representative generator of Microsoft HTML, see https://github.com/riboseinc/asciidoctor-iso
17
+
18
+ Work being tracked at https://github.com/riboseinc/asciidoctor-iso/issues/47:
19
+
20
+ * Render footnotes
21
+ * Render (editorial) comments
22
+ * Render MathML, AsciiMath
23
+
24
+ == Constraints
25
+
26
+ This generates .doc documents.
27
+
28
+ TO DO: compare with https://github.com/MuhammetDilmac/Html2Docx (much simpler, but generates Docx) and https://github.com/jetruby/puredocx (generates Word doc as Ruby object, necessarily simpler).
29
+
30
+ == Usage
31
+
32
+ [source,ruby]
33
+ --
34
+ require "html2doc"
35
+
36
+ Html2Doc.process(result, filename, header_filename, dir)
37
+ --
38
+
39
+ result:: is the Html document to be converted into Word, as a string.
40
+ filename:: is the name the document is to be saved as, without a file suffix
41
+ header_filename:: is the location of the HTML document containing header and footer for the document, as well as footnote/endnote separators; if there is none, use nil. To generate your own such document, save a Word document with headers/footers and/or footnote/endnote separators as an HTML document; the `header.html` will be in the `{filename}.fld` folder generated along with the HTML. A sample file is available at https://github.com/riboseinc/asciidoctor-iso/blob/master/lib/asciidoctor/iso/word/header.html
42
+ dir:: is the directory the document is to be saved to
43
+
44
+ Note that the local CSS file contains a variable `FILENAME` for the location of footnote/endnote separators and headers/footers, which are provided in the header HTML file. The gem replaces `FILENAME` with the file nane that the document will be saved as.
@@ -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
@@ -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__)
@@ -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,46 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "html2doc/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "html2doc"
8
+ spec.version = Html2Doc::VERSION
9
+ spec.authors = ["Ribose Inc."]
10
+ spec.email = ["open.source@ribose.com"]
11
+
12
+ spec.summary = "Convert HTML document to Microsoft Word document"
13
+ "in AsciiDoc."
14
+ spec.description = <<~DESCRIPTION
15
+ Convert HTML document to Microsoft Word document.
16
+
17
+ This gem is in active development.
18
+ DESCRIPTION
19
+
20
+ spec.homepage = "https://github.com/riboseinc/html2doc"
21
+ spec.license = "MIT"
22
+
23
+ spec.bindir = "bin"
24
+ spec.require_paths = ["lib"]
25
+ spec.files = `git ls-files`.split("\n")
26
+ spec.test_files = `git ls-files -- {spec}/*`.split("\n")
27
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
28
+
29
+ spec.add_dependency "htmlentities", "~> 4.3.4"
30
+ spec.add_dependency "image_size"
31
+ spec.add_dependency "mime-types"
32
+ spec.add_dependency "nokogiri", "~> 1.8.1"
33
+ spec.add_dependency "thread_safe"
34
+ spec.add_dependency "uuidtools"
35
+
36
+ spec.add_development_dependency "bundler", "~> 1.15"
37
+ spec.add_development_dependency "byebug", "~> 9.1"
38
+ spec.add_development_dependency "equivalent-xml", "~> 0.6"
39
+ spec.add_development_dependency "guard", "~> 2.14"
40
+ spec.add_development_dependency "guard-rspec", "~> 4.7"
41
+ spec.add_development_dependency "rake", "~> 12.0"
42
+ spec.add_development_dependency "rspec", "~> 3.6"
43
+ spec.add_development_dependency "rubocop", "~> 0.50"
44
+ spec.add_development_dependency "simplecov", "~> 0.15"
45
+ spec.add_development_dependency "timecop", "~> 0.9"
46
+ end
@@ -0,0 +1,2 @@
1
+ require_relative "html2doc/version"
2
+ require_relative "html2doc/base"
@@ -0,0 +1,171 @@
1
+ require "uuidtools"
2
+ require "nokogiri"
3
+
4
+ module Html2Doc
5
+ def self.process(result, filename, header_file, dir)
6
+ # preserve HTML escapes
7
+ unless /<!DOCTYPE html/.match? result
8
+ result.gsub!(/<\?xml version="1.0"\?>/, "")
9
+ result = "<!DOCTYPE html SYSTEM " +
10
+ "'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>" + result
11
+ end
12
+ docxml = Nokogiri::XML(result)
13
+ image_cleanup(docxml, dir)
14
+ define_head(docxml, dir, filename, header_file)
15
+ result = self.msword_fix(docxml.to_xml)
16
+ system "cp #{header_file} #{dir}/header.html" unless header_file.nil?
17
+ generate_filelist(filename, dir)
18
+ File.open("#{filename}.htm", "w") { |f| f.write(result) }
19
+ mime_package result, filename, dir
20
+ end
21
+
22
+ def self.msword_fix(r)
23
+ # brain damage in MSWord parser
24
+ r.gsub(%r{<span style="mso-special-character:footnote"/>},
25
+ '<span style="mso-special-character:footnote"></span>').
26
+ gsub(%r{(<a style="mso-comment-reference:[^>/]+)/>}, "\\1></a>").
27
+ gsub(%r{<link rel="File-List"}, "<link rel=File-List").
28
+ gsub(%r{<meta http-equiv="Content-Type"},
29
+ "<meta http-equiv=Content-Type").
30
+ gsub(%r{&tab;|&amp;tab;},
31
+ '<span style="mso-tab-count:1">&#xA0; </span>')
32
+ end
33
+
34
+ def self.image_resize(orig_filename)
35
+ image_size = ImageSize.path(orig_filename).size
36
+ # max width for Word document is 400, max height is 680
37
+ if image_size[0] > 400
38
+ image_size[1] = (image_size[1] * 400 / image_size[0]).ceil
39
+ image_size[0] = 400
40
+ end
41
+ if image_size[1] > 680
42
+ image_size[0] = (image_size[0] * 680 / image_size[1]).ceil
43
+ image_size[1] = 680
44
+ end
45
+ image_size
46
+ end
47
+
48
+ def self.image_cleanup(docxml, dir)
49
+ docxml.xpath("//*[local-name() = 'img']").each do |i|
50
+ matched = /\.(?<suffix>\S+)$/.match i["src"]
51
+ uuid = UUIDTools::UUID.random_create.to_s
52
+ new_full_filename = File.join(dir, "#{uuid}.#{matched[:suffix]}")
53
+ # presupposes that the image source is local
54
+ system "cp #{i['src']} #{new_full_filename}"
55
+ # image_size = image_resize(i["src"])
56
+ i["width"], i["height"] = image_resize(i["src"])
57
+ i["src"] = new_full_filename
58
+ #i["height"] = image_size[1]
59
+ #i["width"] = image_size[0]
60
+ end
61
+ docxml
62
+ end
63
+
64
+ def self.define_head1(docxml, dir)
65
+ docxml.xpath("//*[local-name() = 'head']").each do |h|
66
+ h.children.first.add_previous_sibling <<~XML
67
+ <!--[if gte mso 9]>
68
+ <xml>
69
+ <w:WordDocument>
70
+ <w:View>Print</w:View>
71
+ <w:Zoom>100</w:Zoom>
72
+ <w:DoNotOptimizeForBrowser/>
73
+ </w:WordDocument>
74
+ </xml>
75
+ <![endif]-->
76
+ <meta http-equiv=Content-Type content="text/html; charset=utf-8"/>
77
+ <link rel="File-List" href="#{dir}/filelist.xml"/>
78
+ XML
79
+ end
80
+ end
81
+
82
+ def self.stylesheet(filename, header_filename)
83
+ fn = File.join(File.dirname(__FILE__), "wordstyle.css")
84
+ stylesheet = File.read(fn, encoding: "UTF-8")
85
+ if header_filename.nil?
86
+ stylesheet.gsub!(/\n[^\n]*FILENAME[^\n]*i\n/, "\n")
87
+ else
88
+ stylesheet.gsub!(/FILENAME/, filename)
89
+ end
90
+ xml = Nokogiri::XML("<style/>")
91
+ xml.children.first << Nokogiri::XML::Comment.new(xml, "\n#{stylesheet}\n")
92
+ xml.root.to_s
93
+ end
94
+
95
+ def self.define_head(docxml, dir, filename, header_file)
96
+ title = docxml.at("//*[local-name() = 'head']/*[local-name() = 'title']")
97
+ head = docxml.at("//*[local-name() = 'head']")
98
+ if title.nil?
99
+ head.children.first.add_previous_sibling stylesheet(filename, header_file)
100
+ else
101
+ title.add_next_sibling stylesheet(filename, header_file)
102
+ end
103
+ self.define_head1(docxml, dir)
104
+ end
105
+
106
+ def self.mime_preamble(boundary, filename, result)
107
+ <<~"PREAMBLE"
108
+ MIME-Version: 1.0
109
+ Content-Type: multipart/related; boundary="#{boundary}"
110
+
111
+ --#{boundary}
112
+ Content-Location: file:///C:/Doc/#{filename}.htm
113
+ Content-Type: text/html; charset="utf-8"
114
+
115
+ #{result}
116
+
117
+ PREAMBLE
118
+ end
119
+
120
+ def self.mime_attachment(boundary, filename, item, dir)
121
+ encoded_file = Base64.strict_encode64(
122
+ File.read("#{dir}/#{item}"),
123
+ ).gsub(/(.{76})/, "\\1\n")
124
+ <<~"FILE"
125
+ --#{boundary}
126
+ Content-Location: file:///C:/Doc/#{filename}_files/#{item}
127
+ Content-Transfer-Encoding: base64
128
+ Content-Type: #{mime_type(item)}
129
+
130
+ #{encoded_file}
131
+
132
+ FILE
133
+ end
134
+
135
+ def self.mime_type(item)
136
+ types = MIME::Types.type_for(item)
137
+ type = types ? types.first.to_s : 'text/plain; charset="utf-8"'
138
+ type = type + ' charset="utf-8"' if /^text/.match?(type) && types
139
+ type
140
+ end
141
+
142
+ def self.mime_boundary
143
+ salt = UUIDTools::UUID.random_create.to_s.gsub(/-/, ".")[0..17]
144
+ "----=_NextPart_#{salt}"
145
+ end
146
+
147
+ def self.mime_package(result, filename, dir)
148
+ boundary = mime_boundary
149
+ mhtml = mime_preamble(boundary, filename, result)
150
+ Dir.foreach(dir) do |item|
151
+ next if item == "." || item == ".." || /^\./.match(item)
152
+ mhtml += mime_attachment(boundary, filename, item, dir)
153
+ end
154
+ mhtml += "--#{boundary}--"
155
+ File.open("#{filename}.doc", "w") { |f| f.write mhtml }
156
+ end
157
+
158
+ def self.generate_filelist(filename, dir)
159
+ File.open(File.join(dir, "filelist.xml"), "w") do |f|
160
+ f.write(<<~"XML")
161
+ <xml xmlns:o="urn:schemas-microsoft-com:office:office">
162
+ <o:MainFile HRef="../#{filename}.htm"/>
163
+ XML
164
+ Dir.foreach(dir) do |item|
165
+ next if item == "." || item == ".." || /^\./.match(item)
166
+ f.write %{ <o:File HRef="#{item}"/>\n}
167
+ end
168
+ f.write("</xml>\n")
169
+ end
170
+ end
171
+ end
@@ -0,0 +1,3822 @@
1
+ <?xml version="1.0" encoding="UTF-8" ?>
2
+ <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:mml="http://www.w3.org/1998/Math/MathML"
3
+ xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math">
4
+ <xsl:output method="xml" encoding="UTF-8" />
5
+
6
+
7
+ <xsl:variable name="StrUCAlphabet">ABCDEFGHIJKLMNOPQRSTUVWXYZ</xsl:variable>
8
+ <xsl:variable name="StrLCAlphabet">abcdefghijklmnopqrstuvwxyz</xsl:variable>
9
+
10
+ <!-- %%Template: match *
11
+
12
+ The catch all template, just passes through
13
+ -->
14
+ <xsl:template match="*">
15
+ <xsl:apply-templates select="*" />
16
+ </xsl:template>
17
+
18
+ <!-- %%Template: match *
19
+
20
+ Another catch all template, just passes through
21
+ -->
22
+ <xsl:template match="/">
23
+ <m:oMath>
24
+ <xsl:apply-templates select="*" />
25
+ </m:oMath>
26
+ </xsl:template>
27
+
28
+ <!-- %%Template: SReplace
29
+
30
+ Replace all occurences of sOrig in sInput with sReplacement
31
+ and return the resulting string. -->
32
+ <xsl:template name="SReplace">
33
+ <xsl:param name="sInput" />
34
+ <xsl:param name="sOrig" />
35
+ <xsl:param name="sReplacement" />
36
+
37
+ <xsl:choose>
38
+ <xsl:when test="not(contains($sInput, $sOrig))">
39
+ <xsl:value-of select="$sInput" />
40
+ </xsl:when>
41
+ <xsl:otherwise>
42
+ <xsl:variable name="sBefore" select="substring-before($sInput, $sOrig)" />
43
+ <xsl:variable name="sAfter" select="substring-after($sInput, $sOrig)" />
44
+ <xsl:variable name="sAfterProcessed">
45
+ <xsl:call-template name="SReplace">
46
+ <xsl:with-param name="sInput" select="$sAfter" />
47
+ <xsl:with-param name="sOrig" select="$sOrig" />
48
+ <xsl:with-param name="sReplacement" select="$sReplacement" />
49
+ </xsl:call-template>
50
+ </xsl:variable>
51
+
52
+ <xsl:value-of select="concat($sBefore, concat($sReplacement, $sAfterProcessed))" />
53
+ </xsl:otherwise>
54
+ </xsl:choose>
55
+ </xsl:template>
56
+
57
+ <!-- %%Template: OutputText
58
+
59
+ Post processing on the string given and otherwise do
60
+ a xsl:value-of on it -->
61
+ <xsl:template name="OutputText">
62
+ <xsl:param name="sInput" />
63
+
64
+ <!-- Add local variable as you add new post processing tasks -->
65
+
66
+ <!-- 1. Remove any unwanted characters -->
67
+ <xsl:variable name="sCharStrip">
68
+ <xsl:value-of select="translate($sInput, '&#x2062;&#x200B;', '')" />
69
+ </xsl:variable>
70
+
71
+ <!-- 2. Replace any characters as needed -->
72
+ <!-- Replace &#x2A75; <-> == -->
73
+ <xsl:variable name="sCharReplace">
74
+ <xsl:call-template name="SReplace">
75
+ <xsl:with-param name="sInput" select="$sCharStrip" />
76
+ <xsl:with-param name="sOrig" select="'&#x2A75;'" />
77
+ <xsl:with-param name="sReplacement" select="'=='" />
78
+ </xsl:call-template>
79
+ </xsl:variable>
80
+
81
+ <!-- Replace &#xa0; (non-breaking space) with ' ' -->
82
+ <xsl:variable name="sCharReplaceFinal" select="translate($sCharReplace, '&#xa0;', ' ')" />
83
+
84
+ <!-- Finally, return the last value -->
85
+ <xsl:value-of select="$sCharReplaceFinal" />
86
+ </xsl:template>
87
+
88
+
89
+ <!-- Template that determines whether or the given node
90
+ ndCur is a token element that doesn't have an mglyph as
91
+ a child.
92
+ -->
93
+ <xsl:template name="FNonGlyphToken">
94
+ <xsl:param name="ndCur" select="." />
95
+ <xsl:choose>
96
+ <xsl:when test="$ndCur/self::mml:mi[not(child::mml:mglyph)] |
97
+ $ndCur/self::mml:mn[not(child::mml:mglyph)] |
98
+ $ndCur/self::mml:mo[not(child::mml:mglyph)] |
99
+ $ndCur/self::mml:ms[not(child::mml:mglyph)] |
100
+ $ndCur/self::mml:mtext[not(child::mml:mglyph)]">1</xsl:when>
101
+ <xsl:otherwise>0</xsl:otherwise>
102
+ </xsl:choose>
103
+ </xsl:template>
104
+
105
+
106
+ <!-- Template used to determine if the current token element (ndCur) is the beginning of a run.
107
+ A token element is the beginning of if:
108
+
109
+ the count of preceding elements is 0
110
+ or
111
+ the directory preceding element is not a non-glyph token.
112
+ -->
113
+ <xsl:template name="FStartOfRun">
114
+ <xsl:param name="ndCur" select="." />
115
+ <xsl:variable name="fPrecSibNonGlyphToken">
116
+ <xsl:call-template name="FNonGlyphToken">
117
+ <xsl:with-param name="ndCur" select="$ndCur/preceding-sibling::*[1]" />
118
+ </xsl:call-template>
119
+ </xsl:variable>
120
+ <xsl:choose>
121
+ <xsl:when test="count($ndCur/preceding-sibling::*)=0
122
+ or $fPrecSibNonGlyphToken=0">1</xsl:when>
123
+ <xsl:otherwise>0</xsl:otherwise>
124
+ </xsl:choose>
125
+ </xsl:template>
126
+
127
+ <!-- Template that determines if ndCur is the argument of an nary expression.
128
+
129
+ ndCur is the argument of an nary expression if:
130
+
131
+ 1. The preceding sibling is one of the following: munder, mover, msub, msup, munder, msubsup, munderover
132
+ and
133
+ 2. The preceding sibling's child is an nary char as specified by the template "isNary"
134
+ -->
135
+ <xsl:template name="FIsNaryArgument">
136
+ <xsl:param name="ndCur" select="." />
137
+
138
+ <xsl:variable name="fNary">
139
+ <xsl:call-template name="isNary">
140
+ <xsl:with-param name="ndCur" select="$ndCur/preceding-sibling::*[1]/child::*[1]" />
141
+ </xsl:call-template>
142
+ </xsl:variable>
143
+ <xsl:choose>
144
+ <xsl:when test="preceding-sibling::*[1][self::mml:munder or self::mml:mover or self::mml:munderover or
145
+ self::mml:msub or self::mml:msup or self::mml:msubsup]
146
+ and $fNary='true'">1</xsl:when>
147
+ <xsl:otherwise>0</xsl:otherwise>
148
+ </xsl:choose>
149
+ </xsl:template>
150
+
151
+ <!-- %%Template: mml:mrow | mml:mstyle
152
+
153
+ if this row is the next sibling of an n-ary (i.e. any of
154
+ mover, munder, munderover, msupsub, msup, or msub with
155
+ the base being an n-ary operator) then ignore this. Otherwise
156
+ pass through -->
157
+ <xsl:template match="mml:mrow|mml:mstyle">
158
+ <xsl:variable name="fNaryArgument">
159
+ <xsl:call-template name="FIsNaryArgument">
160
+ <xsl:with-param name="ndCur" select="."/>
161
+ </xsl:call-template>
162
+ </xsl:variable>
163
+ <xsl:if test="$fNaryArgument=0">
164
+ <xsl:variable name="fLinearFrac">
165
+ <xsl:call-template name="FLinearFrac">
166
+ <xsl:with-param name="ndCur" select="." />
167
+ </xsl:call-template>
168
+ </xsl:variable>
169
+ <xsl:choose>
170
+ <xsl:when test="$fLinearFrac=1">
171
+ <xsl:call-template name="MakeLinearFraction">
172
+ <xsl:with-param name="ndCur" select="." />
173
+ </xsl:call-template>
174
+ </xsl:when>
175
+ <xsl:otherwise>
176
+ <xsl:variable name="fFunc">
177
+ <xsl:call-template name="FIsFunc">
178
+ <xsl:with-param name="ndCur" select="." />
179
+ </xsl:call-template>
180
+ </xsl:variable>
181
+ <xsl:choose>
182
+ <xsl:when test="$fFunc=1">
183
+ <xsl:call-template name="WriteFunc">
184
+ <xsl:with-param name="ndCur" select="." />
185
+ </xsl:call-template>
186
+ </xsl:when>
187
+ <xsl:otherwise>
188
+ <xsl:apply-templates select="*" />
189
+ </xsl:otherwise>
190
+ </xsl:choose>
191
+ </xsl:otherwise>
192
+ </xsl:choose>
193
+ </xsl:if>
194
+ </xsl:template>
195
+ <xsl:template match="mml:mi[not(child::mml:mglyph)] |
196
+ mml:mn[not(child::mml:mglyph)] |
197
+ mml:mo[not(child::mml:mglyph)] |
198
+ mml:ms[not(child::mml:mglyph)] |
199
+ mml:mtext[not(child::mml:mglyph)]">
200
+
201
+ <!-- tokens with mglyphs as children are tranformed
202
+ in a different manner than "normal" token elements.
203
+ Where normal token elements are token elements that
204
+ contain only text -->
205
+ <xsl:variable name="fStartOfRun">
206
+ <xsl:call-template name="FStartOfRun">
207
+ <xsl:with-param name="ndCur" select="." />
208
+ </xsl:call-template>
209
+ </xsl:variable>
210
+
211
+ <!--In MathML, successive characters that are all part of one string are sometimes listed as separate
212
+ tags based on their type (identifier (mi), name (mn), operator (mo), quoted (ms), literal text (mtext)),
213
+ where said tags act to link one another into one logical run. In order to wrap the text of successive mi's,
214
+ mn's, and mo's into one m:t, we need to denote where a run begins. The beginning of a run is the first mi, mn,
215
+ or mo whose immediately preceding sibling either doesn't exist or is something other than a "normal" mi, mn, mo,
216
+ ms, or mtext tag-->
217
+
218
+ <!-- If this mi/mo/mn/ms . . . is part the numerator or denominator of a linear fraction, then don't collect. -->
219
+ <xsl:variable name="fLinearFracParent">
220
+ <xsl:call-template name="FLinearFrac">
221
+ <xsl:with-param name="ndCur" select="parent::*" />
222
+ </xsl:call-template>
223
+ </xsl:variable>
224
+ <!-- If this mi/mo/mn/ms . . . is part of the name of a function, then don't collect. -->
225
+ <xsl:variable name="fFunctionName">
226
+ <xsl:call-template name="FIsFunc">
227
+ <xsl:with-param name="ndCur" select="parent::*" />
228
+ </xsl:call-template>
229
+ </xsl:variable>
230
+ <xsl:variable name="fShouldCollect"
231
+ select="($fLinearFracParent=0 and $fFunctionName=0) and (parent::mml:mrow or parent::mml:mstyle or
232
+ parent::mml:msqrt or parent::mml:menclose or
233
+ parent::mml:math or parent::mml:mphantom or
234
+ parent::mml:mtd or parent::mml:maction)" />
235
+
236
+ <!--In MathML, the meaning of the different parts that make up mathematical structures, such as a fraction
237
+ having a numerator and a denominator, is determined by the relative order of those different parts.
238
+ For instance, In a fraction, the numerator is the first child and the denominator is the second child.
239
+ To allow for more complex structures, MathML allows one to link a group of mi, mn, and mo's together
240
+ using the mrow, or mstyle tags. The mi, mn, and mo's found within any of the above tags are considered
241
+ one run. Therefore, if the parent of any mi, mn, or mo is found to be an mrow or mstyle, then the contiguous
242
+ mi, mn, and mo's will be considered one run.-->
243
+ <xsl:choose>
244
+ <xsl:when test="$fShouldCollect">
245
+ <xsl:choose>
246
+ <xsl:when test="$fStartOfRun=1">
247
+ <!--If this is the beginning of the run, pass all run attributes to CreateRunWithSameProp.-->
248
+ <xsl:call-template name="CreateRunWithSameProp">
249
+ <xsl:with-param name="mathbackground">
250
+ <!-- Look for the unqualified mathml attribute mathbackground.
251
+ Fall back to the qualified mathml attribute if necessary.
252
+ This priority of unqualified over qualified will be
253
+ followed throughout this xslt. -->
254
+ <xsl:choose>
255
+ <xsl:when test="@mathbackground">
256
+ <xsl:value-of select="@mathbackground"/>
257
+ </xsl:when>
258
+ <xsl:otherwise>
259
+ <xsl:value-of select="@mml:mathbackground"/>
260
+ </xsl:otherwise>
261
+ </xsl:choose>
262
+ </xsl:with-param>
263
+ <xsl:with-param name="mathcolor">
264
+ <xsl:choose>
265
+ <xsl:when test="@mathcolor">
266
+ <xsl:value-of select="@mathcolor"/>
267
+ </xsl:when>
268
+ <xsl:otherwise>
269
+ <xsl:value-of select="@mml:mathcolor"/>
270
+ </xsl:otherwise>
271
+ </xsl:choose>
272
+ </xsl:with-param>
273
+ <xsl:with-param name="mathvariant">
274
+ <xsl:choose>
275
+ <xsl:when test="@mathvariant">
276
+ <xsl:value-of select="@mathvariant"/>
277
+ </xsl:when>
278
+ <xsl:otherwise>
279
+ <xsl:value-of select="@mml:mathvariant"/>
280
+ </xsl:otherwise>
281
+ </xsl:choose>
282
+ </xsl:with-param>
283
+ <xsl:with-param name="color">
284
+ <xsl:choose>
285
+ <xsl:when test="@color">
286
+ <xsl:value-of select="@color"/>
287
+ </xsl:when>
288
+ <xsl:otherwise>
289
+ <xsl:value-of select="@mml:color"/>
290
+ </xsl:otherwise>
291
+ </xsl:choose>
292
+ </xsl:with-param>
293
+ <xsl:with-param name="font-family">
294
+ <xsl:choose>
295
+ <xsl:when test="@font-family">
296
+ <xsl:value-of select="@font-family"/>
297
+ </xsl:when>
298
+ <xsl:otherwise>
299
+ <xsl:value-of select="@mml:font-family"/>
300
+ </xsl:otherwise>
301
+ </xsl:choose>
302
+ </xsl:with-param>
303
+ <xsl:with-param name="fontsize">
304
+ <xsl:choose>
305
+ <xsl:when test="@fontsize">
306
+ <xsl:value-of select="@fontsize"/>
307
+ </xsl:when>
308
+ <xsl:otherwise>
309
+ <xsl:value-of select="@mml:fontsize"/>
310
+ </xsl:otherwise>
311
+ </xsl:choose>
312
+ </xsl:with-param>
313
+ <xsl:with-param name="fontstyle">
314
+ <xsl:choose>
315
+ <xsl:when test="@fontstyle">
316
+ <xsl:value-of select="@fontstyle"/>
317
+ </xsl:when>
318
+ <xsl:otherwise>
319
+ <xsl:value-of select="@mml:fontstyle"/>
320
+ </xsl:otherwise>
321
+ </xsl:choose>
322
+ </xsl:with-param>
323
+ <xsl:with-param name="fontweight">
324
+ <xsl:choose>
325
+ <xsl:when test="@fontweight">
326
+ <xsl:value-of select="@fontweight"/>
327
+ </xsl:when>
328
+ <xsl:otherwise>
329
+ <xsl:value-of select="@mml:fontweight"/>
330
+ </xsl:otherwise>
331
+ </xsl:choose>
332
+ </xsl:with-param>
333
+ <xsl:with-param name="mathsize">
334
+ <xsl:choose>
335
+ <xsl:when test="@mathsize">
336
+ <xsl:value-of select="@mathsize"/>
337
+ </xsl:when>
338
+ <xsl:otherwise>
339
+ <xsl:value-of select="@mml:mathsize"/>
340
+ </xsl:otherwise>
341
+ </xsl:choose>
342
+ </xsl:with-param>
343
+ <xsl:with-param name="ndTokenFirst" select="." />
344
+ </xsl:call-template>
345
+ </xsl:when>
346
+ </xsl:choose>
347
+ </xsl:when>
348
+ <xsl:otherwise>
349
+ <!--Only one element will be part of run-->
350
+ <xsl:element name="m:r">
351
+ <!--Create Run Properties based on current node's attributes-->
352
+ <xsl:call-template name="CreateRunProp">
353
+ <xsl:with-param name="mathvariant">
354
+ <xsl:choose>
355
+ <xsl:when test="@mathvariant">
356
+ <xsl:value-of select="@mathvariant"/>
357
+ </xsl:when>
358
+ <xsl:otherwise>
359
+ <xsl:value-of select="@mml:mathvariant"/>
360
+ </xsl:otherwise>
361
+ </xsl:choose>
362
+ </xsl:with-param>
363
+ <xsl:with-param name="fontstyle">
364
+ <xsl:choose>
365
+ <xsl:when test="@fontstyle">
366
+ <xsl:value-of select="@fontstyle"/>
367
+ </xsl:when>
368
+ <xsl:otherwise>
369
+ <xsl:value-of select="@mml:fontstyle"/>
370
+ </xsl:otherwise>
371
+ </xsl:choose>
372
+ </xsl:with-param>
373
+ <xsl:with-param name="fontweight">
374
+ <xsl:choose>
375
+ <xsl:when test="@fontweight">
376
+ <xsl:value-of select="@fontweight"/>
377
+ </xsl:when>
378
+ <xsl:otherwise>
379
+ <xsl:value-of select="@mml:fontweight"/>
380
+ </xsl:otherwise>
381
+ </xsl:choose>
382
+ </xsl:with-param>
383
+ <xsl:with-param name="mathcolor">
384
+ <xsl:choose>
385
+ <xsl:when test="@mathcolor">
386
+ <xsl:value-of select="@mathcolor"/>
387
+ </xsl:when>
388
+ <xsl:otherwise>
389
+ <xsl:value-of select="@mml:mathcolor"/>
390
+ </xsl:otherwise>
391
+ </xsl:choose>
392
+ </xsl:with-param>
393
+ <xsl:with-param name="mathsize">
394
+ <xsl:choose>
395
+ <xsl:when test="@mathsize">
396
+ <xsl:value-of select="@mathsize"/>
397
+ </xsl:when>
398
+ <xsl:otherwise>
399
+ <xsl:value-of select="@mml:mathsize"/>
400
+ </xsl:otherwise>
401
+ </xsl:choose>
402
+ </xsl:with-param>
403
+ <xsl:with-param name="color">
404
+ <xsl:choose>
405
+ <xsl:when test="@color">
406
+ <xsl:value-of select="@color"/>
407
+ </xsl:when>
408
+ <xsl:otherwise>
409
+ <xsl:value-of select="@mml:color"/>
410
+ </xsl:otherwise>
411
+ </xsl:choose>
412
+ </xsl:with-param>
413
+ <xsl:with-param name="fontsize">
414
+ <xsl:choose>
415
+ <xsl:when test="@fontsize">
416
+ <xsl:value-of select="@fontsize"/>
417
+ </xsl:when>
418
+ <xsl:otherwise>
419
+ <xsl:value-of select="@mml:fontsize"/>
420
+ </xsl:otherwise>
421
+ </xsl:choose>
422
+ </xsl:with-param>
423
+ <xsl:with-param name="ndCur" select="." />
424
+ <xsl:with-param name="fNor">
425
+ <xsl:call-template name="FNor">
426
+ <xsl:with-param name="ndCur" select="." />
427
+ </xsl:call-template>
428
+ </xsl:with-param>
429
+ </xsl:call-template>
430
+ <xsl:element name="m:t">
431
+ <xsl:call-template name="OutputText">
432
+ <xsl:with-param name="sInput" select="normalize-space(.)" />
433
+ </xsl:call-template>
434
+ </xsl:element>
435
+ </xsl:element>
436
+ </xsl:otherwise>
437
+ </xsl:choose>
438
+ </xsl:template>
439
+
440
+ <!-- %%Template: CreateRunWithSameProp
441
+ -->
442
+ <xsl:template name="CreateRunWithSameProp">
443
+ <xsl:param name="mathbackground" />
444
+ <xsl:param name="mathcolor" />
445
+ <xsl:param name="mathvariant" />
446
+ <xsl:param name="color" />
447
+ <xsl:param name="font-family" />
448
+ <xsl:param name="fontsize" />
449
+ <xsl:param name="fontstyle" />
450
+ <xsl:param name="fontweight" />
451
+ <xsl:param name="mathsize" />
452
+ <xsl:param name="ndTokenFirst" />
453
+
454
+ <!--Given mathcolor, color, mstyle's (ancestor) color, and precedence of
455
+ said attributes, determine the actual color of the current run-->
456
+ <xsl:variable name="sColorPropCur">
457
+ <xsl:choose>
458
+ <xsl:when test="$mathcolor!=''">
459
+ <xsl:value-of select="$mathcolor" />
460
+ </xsl:when>
461
+ <xsl:when test="$color!=''">
462
+ <xsl:value-of select="$color" />
463
+ </xsl:when>
464
+ <xsl:when test="$ndTokenFirst/ancestor::mml:mstyle[@color][1]/@color!=''">
465
+ <xsl:value-of select="$ndTokenFirst/ancestor::mml:mstyle[@color][1]/@color" />
466
+ </xsl:when>
467
+ <xsl:when test="$ndTokenFirst/ancestor::mml:mstyle[@mml:color][1]/@mml:color!=''">
468
+ <xsl:value-of select="$ndTokenFirst/ancestor::mml:mstyle[@color][1]/@mml:color" />
469
+ </xsl:when>
470
+ <xsl:otherwise>
471
+ <xsl:value-of select="''" />
472
+ </xsl:otherwise>
473
+ </xsl:choose>
474
+ </xsl:variable>
475
+
476
+ <!--Given mathsize, and fontsize and precedence of said attributes,
477
+ determine the actual font size of the current run-->
478
+ <xsl:variable name="sSzCur">
479
+ <xsl:choose>
480
+ <xsl:when test="$mathsize!=''">
481
+ <xsl:value-of select="$mathsize" />
482
+ </xsl:when>
483
+ <xsl:when test="$fontsize!=''">
484
+ <xsl:value-of select="$fontsize" />
485
+ </xsl:when>
486
+ <xsl:otherwise>
487
+ <xsl:value-of select="''" />
488
+ </xsl:otherwise>
489
+ </xsl:choose>
490
+ </xsl:variable>
491
+
492
+ <!--Given mathvariant, fontstyle, and fontweight, and precedence of
493
+ the attributes, determine the actual font of the current run-->
494
+ <xsl:variable name="sFontCur">
495
+ <xsl:call-template name="GetFontCur">
496
+ <xsl:with-param name="mathvariant" select="$mathvariant" />
497
+ <xsl:with-param name="fontstyle" select="$fontstyle" />
498
+ <xsl:with-param name="fontweight" select="$fontweight" />
499
+ <xsl:with-param name="ndCur" select="$ndTokenFirst" />
500
+ </xsl:call-template>
501
+ </xsl:variable>
502
+
503
+ <!-- The omml equivalent structure for mml:mtext is an omml run with the run property m:nor (normal) set.
504
+ Therefore, we can only collect mtexts with other mtext elements. Suppose the $ndTokenFirst is an
505
+ mml:mtext, then if any of its following siblings are to be grouped, they must also be mml:text elements.
506
+ The inverse is also true, suppose the $ndTokenFirst isn't an mml:mtext, then if any of its following siblings
507
+ are to be grouped with $ndTokenFirst, they can't be mml:mtext elements-->
508
+ <xsl:variable name="fNdTokenFirstIsMText">
509
+ <xsl:choose>
510
+ <xsl:when test="$ndTokenFirst/self::mml:mtext">1</xsl:when>
511
+ <xsl:otherwise>0</xsl:otherwise>
512
+ </xsl:choose>
513
+ </xsl:variable>
514
+
515
+ <!--In order to determine the length of the run, we will find the number of nodes before the inital node in the run and
516
+ the number of nodes before the first node that DOES NOT belong to the current run. The number of nodes that will
517
+ be printed is One Less than the difference between the latter and the former-->
518
+
519
+ <!--Find index of current node-->
520
+ <xsl:variable name="nndBeforeFirst" select="count($ndTokenFirst/preceding-sibling::*)" />
521
+
522
+ <!--Find index of next change in run properties.
523
+
524
+ The basic idea is that we want to find the position of the last node in the longest
525
+ sequence of nodes, starting from ndTokenFirst, that can be grouped into a run. For
526
+ example, nodes A and B can be grouped together into the same run iff they have the same
527
+ props.
528
+
529
+ To accomplish this grouping, we want to find the next sibling to ndTokenFirst that shouldn't be
530
+ included in the run of text. We do this by counting the number of elements that precede the first
531
+ such element that doesn't belong. The xpath that accomplishes this is below.
532
+
533
+ Count the number of siblings the precede the first element after ndTokenFirst that shouldn't belong.
534
+ count($ndTokenFirst/following-sibling::*[ . . . ][1]/preceding-sibling::*)
535
+
536
+ Now, the hard part to this is what is represented by the '. . .' above. This conditional expression is
537
+ defining what elements *don't* belong to the current run. The conditions are as follows:
538
+
539
+ The element is not a token element (mi, mn, mo, ms, or mtext)
540
+
541
+ or
542
+
543
+ The token element contains a glyph child (this is handled separately).
544
+
545
+ or
546
+
547
+ The token is an mtext and the run didn't start with an mtext, or the token isn't an mtext and the run started
548
+ with an mtext. We do this check because mtext transforms into an omml m:nor property, and thus, these mtext
549
+ token elements need to be grouped separately from other token elements.
550
+
551
+ // We do an or not( . . . ), because it was easier to define what token elements match than how they don't match.
552
+ // Thus, this inner '. . .' defines how token attributes equate to one another. We add the 'not' outside of to accomplish
553
+ // the goal of the outer '. . .', which is the find the next element that *doesn't* match.
554
+ or not(
555
+ The background colors match.
556
+
557
+ and
558
+
559
+ The current font (sFontCur) matches the mathvariant
560
+
561
+ or
562
+
563
+ sFontCur is normal and matches the current font characteristics
564
+
565
+ or
566
+
567
+ sFontCur is italic and matches the current font characteristics
568
+
569
+ or
570
+
571
+ . . .
572
+
573
+ and
574
+
575
+ The font family matches the current font family.
576
+ ) // end of not().-->
577
+ <xsl:variable name="nndBeforeLim" select="count($ndTokenFirst/following-sibling::*
578
+ [(not(self::mml:mi) and not(self::mml:mn) and not(self::mml:mo) and not(self::mml:ms) and not(self::mml:mtext))
579
+ or
580
+ (self::mml:mi[child::mml:mglyph] or self::mml:mn[child::mml:mglyph] or self::mml:mo[child::mml:mglyph] or self::mml:ms[child::mml:mglyph] or self::mml:mtext[child::mml:mglyph])
581
+ or
582
+ (($fNdTokenFirstIsMText=1 and not(self::mml:mtext)) or ($fNdTokenFirstIsMText=0 and self::mml:mtext))
583
+ or
584
+ not(
585
+ ((($sFontCur=@mathvariant or $sFontCur=@mml:mathvariant)
586
+ or
587
+ ($sFontCur='normal'
588
+ and ((@mathvariant='normal' or @mml:mathvariant='normal')
589
+ or (((not(@mathvariant) or @mathvariant='') and (not(@mml:mathvariant) or @mml:mathvariant=''))
590
+ and (
591
+ ((@fontstyle='normal' or @mml:fontstyle='normal') and (not(@fontweight='bold') and not(@mml:fontweight='bold')))
592
+ or (self::mml:mi and string-length(normalize-space(.)) &gt; 1)
593
+ or (self::mml:mn and string(number(self::mml:mn/text()))='NaN')
594
+ )
595
+ )
596
+ )
597
+ )
598
+ or
599
+ ($sFontCur='italic'
600
+ and ((@mathvariant='italic' or @mml:mathvariant='italic')
601
+ or (((not(@mathvariant) or @mathvariant='') and (not(@mml:mathvariant) or @mml:mathvariant=''))
602
+ and (
603
+ ((@fontstyle='italic' or @mml:fontstyle='italic') and (not(@fontweight='bold') and not(@mml:fontweight='bold')))
604
+ or
605
+ ((self::mml:mn and string(number(self::mml:mn/text()))!='NaN')
606
+ or self::mml:mo
607
+ or (self::mml:mi and string-length(normalize-space(.)) &lt;= 1)
608
+ )
609
+ )
610
+ )
611
+ )
612
+ )
613
+ or
614
+ ($sFontCur='bold'
615
+ and ((@mathvariant='bold' or @mml:mathvariant='bold')
616
+ or (((not(@mathvariant) or @mathvariant='') and (not(@mml:mathvariant) or @mml:mathvariant=''))
617
+ and (
618
+ ((@fontweight='bold' or @mml:fontweight='bold')
619
+ and ((@fontstyle='normal' or @mml:fontstyle='normal') or (self::mml:mi and string-length(normalize-space(.)) &lt;= 1))
620
+ )
621
+ )
622
+ )
623
+ )
624
+ )
625
+ or
626
+ (($sFontCur='bi' or $sFontCur='bold-italic')
627
+ and (
628
+ (@mathvariant='bold-italic' or @mml:mathvariant='bold-italic')
629
+ or (((not(@mathvariant) or @mathvariant='') and (not(@mml:mathvariant) or @mml:mathvariant=''))
630
+ and (
631
+ ((@fontweight='bold' or @mml:fontweight='bold') and (@fontstyle='italic' or @mml:fontstyle='italic'))
632
+ or ((@fontweight='bold' or @mml:fontweight='bold')
633
+ and (self::mml:mn
634
+ or self::mml:mo
635
+ or (self::mml:mi and string-length(normalize-space(.)) &lt;= 1)))
636
+ )
637
+ )
638
+ )
639
+ )
640
+ or
641
+ (($sFontCur=''
642
+ and (
643
+ ((not(@mathvariant) or @mathvariant='')
644
+ and (not(@mml:mathvariant) or @mml:mathvariant='')
645
+ and (not(@fontstyle) or @fontstyle='')
646
+ and (not(@mml:fontstyle) or @mml:fontstyle='')
647
+ and (not(@fontweight)or @fontweight='')
648
+ and (not(@mml:fontweight) or @mml:fontweight='')
649
+ )
650
+ or
651
+ (@mathvariant='italic' or @mml:mathvariant='italic')
652
+ or (
653
+ ((not(@mathvariant) or @mathvariant='') and (not(@mml:mathvariant) or @mml:mathvariant=''))
654
+ and (
655
+ (((@fontweight='normal' or @mml:fontweight='normal')
656
+ and (@fontstyle='italic' or @mml:fontstyle='italic'))
657
+ )
658
+ or
659
+ ((not(@fontweight) or @fontweight='') and (not(@mml:fontweight) or @mml:fontweight=''))
660
+ and (@fontstyle='italic' or @mml:fontstyle='italic')
661
+ or
662
+ ((not(@fontweight) or @fontweight='') and (not(@mml:fontweight) or @mml:fontweight=''))
663
+ and (not(@fontstyle) or @fontstyle='')
664
+ and (not(@mml:fontstyle) or @mml:fontstyle=''))
665
+ )
666
+ )
667
+
668
+ ))
669
+ or
670
+ ($sFontCur='normal'
671
+ and ((self::mml:mi
672
+ and (not(@mathvariant) or @mathvariant='')
673
+ and (not(@mml:mathvariant) or @mml:mathvariant)
674
+ and (not(@fontstyle) or @fontstyle='')
675
+ and (not(@mml:fontstyle) or @mml:fontstyle='')
676
+ and (not(@fontweight) or @fontweight='')
677
+ and (not(@mml:fontweight) or @mml:fontweight='')
678
+ and (string-length(normalize-space(.)) &gt; 1)
679
+ )
680
+ or ((self::mml:ms or self::mml:mtext)
681
+ and (not(@mathvariant) or @mathvariant='')
682
+ and (not(@mml:mathvariant) or @mml:mathvariant)
683
+ and (not(@fontstyle) or @fontstyle)
684
+ and (not(@fontstyle) or @fontstyle='')
685
+ and (not(@fontweight) or @fontweight)
686
+ and (not(@mml:fontweight) or @mml:fontweight='')
687
+ )
688
+ )
689
+ )
690
+ )
691
+ and
692
+ (($font-family = @font-family or $font-family = @mml:font-family)
693
+ or (($font-family='' or not($font-family))
694
+ and (not(@font-family) or @font-family='')
695
+ and (not(@mml:font-family) or @mml:font-family='')
696
+ )
697
+ )
698
+ ))
699
+ ][1]/preceding-sibling::*)" />
700
+
701
+ <xsl:variable name="cndRun" select="$nndBeforeLim - $nndBeforeFirst" />
702
+
703
+ <!--Contiguous groups of like-property mi, mn, and mo's are separated by non- mi, mn, mo tags, or mi,mn, or mo
704
+ tags with different properties. nndBeforeLim is the number of nodes before the next tag which separates contiguous
705
+ groups of like-property mi, mn, and mo's. Knowing this delimiting tag allows for the aggregation of the correct
706
+ number of mi, mn, and mo tags.-->
707
+ <xsl:element name="m:r">
708
+
709
+ <!--The beginning and ending of the current run has been established. Now we should open a run element-->
710
+ <xsl:choose>
711
+
712
+ <!--If cndRun > 0, then there is a following diffrent prop, or non- Token,
713
+ although there may or may not have been a preceding different prop, or non-
714
+ Token-->
715
+ <xsl:when test="$cndRun &gt; 0">
716
+ <xsl:call-template name="CreateRunProp">
717
+ <xsl:with-param name="mathvariant" select="$mathvariant" />
718
+ <xsl:with-param name="fontstyle" select="$fontstyle" />
719
+ <xsl:with-param name="fontweight" select="$fontweight" />
720
+ <xsl:with-param name="mathcolor" select="$mathcolor" />
721
+ <xsl:with-param name="mathsize" select="$mathsize" />
722
+ <xsl:with-param name="color" select="$color" />
723
+ <xsl:with-param name="fontsize" select="$fontsize" />
724
+ <xsl:with-param name="ndCur" select="$ndTokenFirst" />
725
+ <xsl:with-param name="fNor">
726
+ <xsl:call-template name="FNor">
727
+ <xsl:with-param name="ndCur" select="$ndTokenFirst" />
728
+ </xsl:call-template>
729
+ </xsl:with-param>
730
+ </xsl:call-template>
731
+ <xsl:element name="m:t">
732
+ <xsl:call-template name="OutputText">
733
+ <xsl:with-param name="sInput">
734
+ <xsl:choose>
735
+ <xsl:when test="namespace-uri($ndTokenFirst) = 'http://www.w3.org/1998/Math/MathML' and local-name($ndTokenFirst) = 'ms'">
736
+ <xsl:call-template name="OutputMs">
737
+ <xsl:with-param name="msCur" select="$ndTokenFirst" />
738
+ </xsl:call-template>
739
+ </xsl:when>
740
+ <xsl:otherwise>
741
+ <xsl:value-of select="normalize-space($ndTokenFirst)" />
742
+ </xsl:otherwise>
743
+ </xsl:choose>
744
+ <xsl:for-each select="$ndTokenFirst/following-sibling::*[position() &lt; $cndRun]">
745
+ <xsl:choose>
746
+ <xsl:when test="namespace-uri(.) = 'http://www.w3.org/1998/Math/MathML' and
747
+ local-name(.) = 'ms'">
748
+ <xsl:call-template name="OutputMs">
749
+ <xsl:with-param name="msCur" select="." />
750
+ </xsl:call-template>
751
+ </xsl:when>
752
+ <xsl:otherwise>
753
+ <xsl:value-of select="normalize-space(.)" />
754
+ </xsl:otherwise>
755
+ </xsl:choose>
756
+ </xsl:for-each>
757
+ </xsl:with-param>
758
+ </xsl:call-template>
759
+ </xsl:element>
760
+ </xsl:when>
761
+ <xsl:otherwise>
762
+
763
+ <!--if cndRun lt;= 0, then iNextNonToken = 0,
764
+ and iPrecNonToken gt;= 0. In either case, b/c there
765
+ is no next different property or non-Token
766
+ (which is implied by the nndBeforeLast being equal to 0)
767
+ you can put all the remaining mi, mn, and mo's into one
768
+ group.-->
769
+ <xsl:call-template name="CreateRunProp">
770
+ <xsl:with-param name="mathvariant" select="$mathvariant" />
771
+ <xsl:with-param name="fontstyle" select="$fontstyle" />
772
+ <xsl:with-param name="fontweight" select="$fontweight" />
773
+ <xsl:with-param name="mathcolor" select="$mathcolor" />
774
+ <xsl:with-param name="mathsize" select="$mathsize" />
775
+ <xsl:with-param name="color" select="$color" />
776
+ <xsl:with-param name="fontsize" select="$fontsize" />
777
+ <xsl:with-param name="ndCur" select="$ndTokenFirst" />
778
+ <xsl:with-param name="fNor">
779
+ <xsl:call-template name="FNor">
780
+ <xsl:with-param name="ndCur" select="$ndTokenFirst" />
781
+ </xsl:call-template>
782
+ </xsl:with-param>
783
+ </xsl:call-template>
784
+ <xsl:element name="m:t">
785
+
786
+ <!--Create the Run, first output current, then in a
787
+ for-each, because all the following siblings are
788
+ mn, mi, and mo's that conform to the run's properties,
789
+ group them together-->
790
+ <xsl:call-template name="OutputText">
791
+ <xsl:with-param name="sInput">
792
+ <xsl:choose>
793
+ <xsl:when test="namespace-uri($ndTokenFirst) = 'http://www.w3.org/1998/Math/MathML' and
794
+ local-name($ndTokenFirst) = 'ms'">
795
+ <xsl:call-template name="OutputMs">
796
+ <xsl:with-param name="msCur" select="$ndTokenFirst" />
797
+ </xsl:call-template>
798
+ </xsl:when>
799
+ <xsl:otherwise>
800
+ <xsl:value-of select="normalize-space($ndTokenFirst)" />
801
+ </xsl:otherwise>
802
+ </xsl:choose>
803
+ <xsl:for-each select="$ndTokenFirst/following-sibling::*[self::mml:mi or self::mml:mn or self::mml:mo or self::mml:ms or self::mml:mtext]">
804
+ <xsl:choose>
805
+ <xsl:when test="namespace-uri(.) = 'http://www.w3.org/1998/Math/MathML' and
806
+ local-name(.) = 'ms'">
807
+ <xsl:call-template name="OutputMs">
808
+ <xsl:with-param name="msCur" select="." />
809
+ </xsl:call-template>
810
+ </xsl:when>
811
+ <xsl:otherwise>
812
+ <xsl:value-of select="normalize-space(.)" />
813
+ </xsl:otherwise>
814
+ </xsl:choose>
815
+ </xsl:for-each>
816
+ </xsl:with-param>
817
+ </xsl:call-template>
818
+ </xsl:element>
819
+ </xsl:otherwise>
820
+ </xsl:choose>
821
+ </xsl:element>
822
+
823
+ <!--The run was terminated by an mi, mn, mo, ms, or mtext with different properties,
824
+ therefore, call-template CreateRunWithSameProp, using cndRun+1 node as new start node-->
825
+ <xsl:if test="$nndBeforeLim!=0
826
+ and ($ndTokenFirst/following-sibling::*[$cndRun]/self::mml:mi or
827
+ $ndTokenFirst/following-sibling::*[$cndRun]/self::mml:mn or
828
+ $ndTokenFirst/following-sibling::*[$cndRun]/self::mml:mo or
829
+ $ndTokenFirst/following-sibling::*[$cndRun]/self::mml:ms or
830
+ $ndTokenFirst/following-sibling::*[$cndRun]/self::mml:mtext)
831
+ and (count($ndTokenFirst/following-sibling::*[$cndRun]/mml:mglyph) = 0)">
832
+ <xsl:call-template name="CreateRunWithSameProp">
833
+ <xsl:with-param name="mathbackground">
834
+ <xsl:choose>
835
+ <xsl:when test="$ndTokenFirst/following-sibling::*[$cndRun]/@mathbackground">
836
+ <xsl:value-of select="$ndTokenFirst/following-sibling::*[$cndRun]/@mathbackground"/>
837
+ </xsl:when>
838
+ <xsl:otherwise>
839
+ <xsl:value-of select="$ndTokenFirst/following-sibling::*[$cndRun]/@mml:mathbackground"/>
840
+ </xsl:otherwise>
841
+ </xsl:choose>
842
+ </xsl:with-param>
843
+ <xsl:with-param name="mathcolor">
844
+ <xsl:choose>
845
+ <xsl:when test="$ndTokenFirst/following-sibling::*[$cndRun]/@mathcolor">
846
+ <xsl:value-of select="$ndTokenFirst/following-sibling::*[$cndRun]/@mathcolor"/>
847
+ </xsl:when>
848
+ <xsl:otherwise>
849
+ <xsl:value-of select="$ndTokenFirst/following-sibling::*[$cndRun]/@mml:mathcolor"/>
850
+ </xsl:otherwise>
851
+ </xsl:choose>
852
+ </xsl:with-param>
853
+ <xsl:with-param name="mathvariant">
854
+ <xsl:choose>
855
+ <xsl:when test="$ndTokenFirst/following-sibling::*[$cndRun]/@mathvariant">
856
+ <xsl:value-of select="$ndTokenFirst/following-sibling::*[$cndRun]/@mathvariant"/>
857
+ </xsl:when>
858
+ <xsl:otherwise>
859
+ <xsl:value-of select="$ndTokenFirst/following-sibling::*[$cndRun]/@mml:mathvariant"/>
860
+ </xsl:otherwise>
861
+ </xsl:choose>
862
+ </xsl:with-param>
863
+ <xsl:with-param name="color">
864
+ <xsl:choose>
865
+ <xsl:when test="$ndTokenFirst/following-sibling::*[$cndRun]/@color">
866
+ <xsl:value-of select="$ndTokenFirst/following-sibling::*[$cndRun]/@color"/>
867
+ </xsl:when>
868
+ <xsl:otherwise>
869
+ <xsl:value-of select="$ndTokenFirst/following-sibling::*[$cndRun]/@mml:color"/>
870
+ </xsl:otherwise>
871
+ </xsl:choose>
872
+ </xsl:with-param>
873
+ <xsl:with-param name="font-family">
874
+ <xsl:choose>
875
+ <xsl:when test="$ndTokenFirst/following-sibling::*[$cndRun]/@font-family">
876
+ <xsl:value-of select="$ndTokenFirst/following-sibling::*[$cndRun]/@font-family"/>
877
+ </xsl:when>
878
+ <xsl:otherwise>
879
+ <xsl:value-of select="$ndTokenFirst/following-sibling::*[$cndRun]/@mml:font-family"/>
880
+ </xsl:otherwise>
881
+ </xsl:choose>
882
+ </xsl:with-param>
883
+ <xsl:with-param name="fontsize">
884
+ <xsl:choose>
885
+ <xsl:when test="$ndTokenFirst/following-sibling::*[$cndRun]/@fontsize">
886
+ <xsl:value-of select="$ndTokenFirst/following-sibling::*[$cndRun]/@fontsize"/>
887
+ </xsl:when>
888
+ <xsl:otherwise>
889
+ <xsl:value-of select="$ndTokenFirst/following-sibling::*[$cndRun]/@mml:fontsize"/>
890
+ </xsl:otherwise>
891
+ </xsl:choose>
892
+ </xsl:with-param>
893
+ <xsl:with-param name="fontstyle">
894
+ <xsl:choose>
895
+ <xsl:when test="$ndTokenFirst/following-sibling::*[$cndRun]/@fontstyle">
896
+ <xsl:value-of select="$ndTokenFirst/following-sibling::*[$cndRun]/@fontstyle"/>
897
+ </xsl:when>
898
+ <xsl:otherwise>
899
+ <xsl:value-of select="$ndTokenFirst/following-sibling::*[$cndRun]/@mml:fontstyle"/>
900
+ </xsl:otherwise>
901
+ </xsl:choose>
902
+ </xsl:with-param>
903
+ <xsl:with-param name="fontweight">
904
+ <xsl:choose>
905
+ <xsl:when test="$ndTokenFirst/following-sibling::*[$cndRun]/@fontweight">
906
+ <xsl:value-of select="$ndTokenFirst/following-sibling::*[$cndRun]/@fontweight"/>
907
+ </xsl:when>
908
+ <xsl:otherwise>
909
+ <xsl:value-of select="$ndTokenFirst/following-sibling::*[$cndRun]/@mml:fontweight"/>
910
+ </xsl:otherwise>
911
+ </xsl:choose>
912
+ </xsl:with-param>
913
+ <xsl:with-param name="mathsize">
914
+ <xsl:choose>
915
+ <xsl:when test="$ndTokenFirst/following-sibling::*[$cndRun]/@mathsize">
916
+ <xsl:value-of select="$ndTokenFirst/following-sibling::*[$cndRun]/@mathsize"/>
917
+ </xsl:when>
918
+ <xsl:otherwise>
919
+ <xsl:value-of select="$ndTokenFirst/following-sibling::*[$cndRun]/@mml:mathsize"/>
920
+ </xsl:otherwise>
921
+ </xsl:choose>
922
+ </xsl:with-param>
923
+ <xsl:with-param name="ndTokenFirst" select="$ndTokenFirst/following-sibling::*[$cndRun]" />
924
+ </xsl:call-template>
925
+ </xsl:if>
926
+ </xsl:template>
927
+
928
+ <!-- %%Template: FNor
929
+ Given the context of ndCur, determine if ndCur should be omml's normal style.
930
+ -->
931
+ <xsl:template name="FNor">
932
+ <xsl:param name="ndCur" select="." />
933
+ <xsl:choose>
934
+ <!-- Is the current node an mml:mtext, or if this is an mglyph whose parent is
935
+ an mml:mtext. -->
936
+ <xsl:when test="$ndCur/self::mml:mtext or ($ndCur/self::mml:mglyph and parent::mml:mtext)">1</xsl:when>
937
+ <xsl:otherwise>0</xsl:otherwise>
938
+ </xsl:choose>
939
+ </xsl:template>
940
+
941
+
942
+ <!-- %%Template: CreateRunProp
943
+ -->
944
+ <xsl:template name="CreateRunProp">
945
+ <xsl:param name="mathbackground" />
946
+ <xsl:param name="mathcolor" />
947
+ <xsl:param name="mathvariant" />
948
+ <xsl:param name="color" />
949
+ <xsl:param name="font-family" />
950
+ <xsl:param name="fontsize" />
951
+ <xsl:param name="fontstyle" />
952
+ <xsl:param name="fontweight" />
953
+ <xsl:param name="mathsize" />
954
+ <xsl:param name="ndCur" />
955
+ <xsl:param name="fontfamily" />
956
+ <xsl:param name="fNor" />
957
+ <xsl:variable name="mstyleColor">
958
+ <xsl:if test="not(not($ndCur))">
959
+ <xsl:choose>
960
+ <xsl:when test="$ndCur/ancestor::mml:mstyle[@color][1]/@color">
961
+ <xsl:value-of select="$ndCur/ancestor::mml:mstyle[@color][1]/@color"/>
962
+ </xsl:when>
963
+ <xsl:otherwise>
964
+ <xsl:value-of select="$ndCur/ancestor::mml:mstyle[@color][1]/@mml:color"/>
965
+ </xsl:otherwise>
966
+ </xsl:choose>
967
+ </xsl:if>
968
+ </xsl:variable>
969
+ <xsl:call-template name="CreateMathRPR">
970
+ <xsl:with-param name="mathvariant" select="$mathvariant" />
971
+ <xsl:with-param name="fontstyle" select="$fontstyle" />
972
+ <xsl:with-param name="fontweight" select="$fontweight" />
973
+ <xsl:with-param name="ndCur" select="$ndCur" />
974
+ <xsl:with-param name="fNor" select="$fNor" />
975
+ </xsl:call-template>
976
+ </xsl:template>
977
+
978
+ <!-- %%Template: CreateMathRPR
979
+ -->
980
+ <xsl:template name="CreateMathRPR">
981
+ <xsl:param name="mathvariant" />
982
+ <xsl:param name="fontstyle" />
983
+ <xsl:param name="fontweight" />
984
+ <xsl:param name="ndCur" />
985
+ <xsl:param name="fNor" />
986
+ <xsl:variable name="sFontCur">
987
+ <xsl:call-template name="GetFontCur">
988
+ <xsl:with-param name="mathvariant" select="$mathvariant" />
989
+ <xsl:with-param name="fontstyle" select="$fontstyle" />
990
+ <xsl:with-param name="fontweight" select="$fontweight" />
991
+ <xsl:with-param name="ndCur" select="$ndCur" />
992
+ </xsl:call-template>
993
+ </xsl:variable>
994
+ <xsl:if test="$fNor=1 or ($sFontCur!='italic' and $sFontCur!='')">
995
+ <xsl:element name="m:rPr">
996
+ <xsl:if test="$fNor=1">
997
+ <m:nor />
998
+ </xsl:if>
999
+ <xsl:call-template name="CreateMathScrStyProp">
1000
+ <xsl:with-param name="font" select="$sFontCur" />
1001
+ <xsl:with-param name="fNor" select="$fNor" />
1002
+ </xsl:call-template>
1003
+ </xsl:element>
1004
+ </xsl:if>
1005
+ </xsl:template>
1006
+
1007
+ <!-- %%Template: GetFontCur
1008
+ -->
1009
+ <xsl:template name="GetFontCur">
1010
+ <xsl:param name="ndCur" />
1011
+ <xsl:param name="mathvariant" />
1012
+ <xsl:param name="fontstyle" />
1013
+ <xsl:param name="fontweight" />
1014
+ <xsl:choose>
1015
+ <xsl:when test="$mathvariant!=''">
1016
+ <xsl:value-of select="$mathvariant" />
1017
+ </xsl:when>
1018
+ <xsl:when test="not($ndCur)">
1019
+ <xsl:value-of select="'italic'" />
1020
+ </xsl:when>
1021
+ <xsl:when test="$ndCur/self::mml:mi and (string-length(normalize-space($ndCur)) &lt;= 1)
1022
+ or $ndCur/self::mml:mn and string(number($ndCur/text()))!='NaN'
1023
+ or $ndCur/self::mml:mo">
1024
+
1025
+ <!-- The default for the above three cases is fontstyle=italic fontweight=normal.-->
1026
+ <xsl:choose>
1027
+ <xsl:when test="$fontstyle='normal' and $fontweight='bold'">
1028
+ <!-- In omml, a sty of 'b' (which is what bold is translated into)
1029
+ implies a normal fontstyle -->
1030
+ <xsl:value-of select="'bold'" />
1031
+ </xsl:when>
1032
+ <xsl:when test="$fontstyle='normal'">
1033
+ <xsl:value-of select="'normal'" />
1034
+ </xsl:when>
1035
+ <xsl:when test="$fontweight='bold'">
1036
+ <xsl:value-of select="'bi'" />
1037
+ </xsl:when>
1038
+ <xsl:otherwise>
1039
+ <xsl:value-of select="'italic'" />
1040
+ </xsl:otherwise>
1041
+ </xsl:choose>
1042
+ </xsl:when>
1043
+ <xsl:otherwise>
1044
+ <!--Default is fontweight = 'normal' and fontstyle='normal'-->
1045
+ <xsl:choose>
1046
+ <xsl:when test="$fontstyle='italic' and $fontweight='bold'">
1047
+ <xsl:value-of select="'bi'" />
1048
+ </xsl:when>
1049
+ <xsl:when test="$fontstyle='italic'">
1050
+ <xsl:value-of select="'italic'" />
1051
+ </xsl:when>
1052
+ <xsl:when test="$fontweight='bold'">
1053
+ <xsl:value-of select="'bold'" />
1054
+ </xsl:when>
1055
+ <xsl:otherwise>
1056
+ <xsl:value-of select="'normal'" />
1057
+ </xsl:otherwise>
1058
+ </xsl:choose>
1059
+ </xsl:otherwise>
1060
+ </xsl:choose>
1061
+ </xsl:template>
1062
+
1063
+
1064
+ <!-- %%Template: CreateMathScrStyProp
1065
+ -->
1066
+ <xsl:template name="CreateMathScrStyProp">
1067
+ <xsl:param name="font" />
1068
+ <xsl:param name="fNor" select="0"/>
1069
+ <xsl:choose>
1070
+ <xsl:when test="$font='normal' and $fNor=0">
1071
+ <xsl:element name="m:sty">
1072
+ <xsl:attribute name="m:val">p</xsl:attribute>
1073
+ </xsl:element>
1074
+ </xsl:when>
1075
+ <xsl:when test="$font='bold'">
1076
+ <xsl:element name="m:sty">
1077
+ <xsl:attribute name="m:val">b</xsl:attribute>
1078
+ </xsl:element>
1079
+ </xsl:when>
1080
+ <xsl:when test="$font='italic'">
1081
+ </xsl:when>
1082
+ <xsl:when test="$font='script'">
1083
+ <xsl:element name="m:scr">
1084
+ <xsl:attribute name="m:val">script</xsl:attribute>
1085
+ </xsl:element>
1086
+ </xsl:when>
1087
+ <xsl:when test="$font='bold-script'">
1088
+ <xsl:element name="m:scr">
1089
+ <xsl:attribute name="m:val">script</xsl:attribute>
1090
+ </xsl:element>
1091
+ <xsl:element name="m:sty">
1092
+ <xsl:attribute name="m:val">b</xsl:attribute>
1093
+ </xsl:element>
1094
+ </xsl:when>
1095
+ <xsl:when test="$font='double-struck'">
1096
+ <xsl:element name="m:scr">
1097
+ <xsl:attribute name="m:val">double-struck</xsl:attribute>
1098
+ </xsl:element>
1099
+ <xsl:element name="m:sty">
1100
+ <xsl:attribute name="m:val">p</xsl:attribute>
1101
+ </xsl:element>
1102
+ </xsl:when>
1103
+ <xsl:when test="$font='fraktur'">
1104
+ <xsl:element name="m:scr">
1105
+ <xsl:attribute name="m:val">fraktur</xsl:attribute>
1106
+ </xsl:element>
1107
+ <xsl:element name="m:sty">
1108
+ <xsl:attribute name="m:val">p</xsl:attribute>
1109
+ </xsl:element>
1110
+ </xsl:when>
1111
+ <xsl:when test="$font='bold-fraktur'">
1112
+ <xsl:element name="m:scr">
1113
+ <xsl:attribute name="m:val">fraktur</xsl:attribute>
1114
+ </xsl:element>
1115
+ <xsl:element name="m:sty">
1116
+ <xsl:attribute name="m:val">b</xsl:attribute>
1117
+ </xsl:element>
1118
+ </xsl:when>
1119
+ <xsl:when test="$font='sans-serif'">
1120
+ <xsl:element name="m:scr">
1121
+ <xsl:attribute name="m:val">sans-serif</xsl:attribute>
1122
+ </xsl:element>
1123
+ <xsl:element name="m:sty">
1124
+ <xsl:attribute name="m:val">p</xsl:attribute>
1125
+ </xsl:element>
1126
+ </xsl:when>
1127
+ <xsl:when test="$font='bold-sans-serif'">
1128
+ <xsl:element name="m:scr">
1129
+ <xsl:attribute name="m:val">sans-serif</xsl:attribute>
1130
+ </xsl:element>
1131
+ <xsl:element name="m:sty">
1132
+ <xsl:attribute name="m:val">b</xsl:attribute>
1133
+ </xsl:element>
1134
+ </xsl:when>
1135
+ <xsl:when test="$font='sans-serif-italic'">
1136
+ <xsl:element name="m:scr">
1137
+ <xsl:attribute name="m:val">sans-serif</xsl:attribute>
1138
+ </xsl:element>
1139
+ </xsl:when>
1140
+ <xsl:when test="$font='sans-serif-bold-italic'">
1141
+ <xsl:element name="m:scr">
1142
+ <xsl:attribute name="m:val">sans-serif</xsl:attribute>
1143
+ </xsl:element>
1144
+ <xsl:element name="m:sty">
1145
+ <xsl:attribute name="m:val">bi</xsl:attribute>
1146
+ </xsl:element>
1147
+ </xsl:when>
1148
+ <xsl:when test="$font='monospace'" />
1149
+ <!-- We can't do monospace, so leave empty -->
1150
+ <xsl:when test="$font='bold'">
1151
+ <xsl:element name="m:sty">
1152
+ <xsl:attribute name="m:val">b</xsl:attribute>
1153
+ </xsl:element>
1154
+ </xsl:when>
1155
+ <xsl:when test="$font='bi' or $font='bold-italic'">
1156
+ <xsl:element name="m:sty">
1157
+ <xsl:attribute name="m:val">bi</xsl:attribute>
1158
+ </xsl:element>
1159
+ </xsl:when>
1160
+ </xsl:choose>
1161
+ </xsl:template>
1162
+
1163
+ <xsl:template name="FBar">
1164
+ <xsl:param name="sLineThickness" />
1165
+ <xsl:variable name="sLowerLineThickness" select="translate($sLineThickness, $StrUCAlphabet, $StrLCAlphabet)" />
1166
+ <xsl:choose>
1167
+ <xsl:when test="string-length($sLowerLineThickness)=0
1168
+ or $sLowerLineThickness='thin'
1169
+ or $sLowerLineThickness='medium'
1170
+ or $sLowerLineThickness='thick'">1</xsl:when>
1171
+ <xsl:otherwise>
1172
+ <xsl:variable name="fStrContainsNonZeroDigit">
1173
+ <xsl:call-template name="FStrContainsNonZeroDigit">
1174
+ <xsl:with-param name="s" select="$sLowerLineThickness" />
1175
+ </xsl:call-template>
1176
+ </xsl:variable>
1177
+ <xsl:choose>
1178
+ <xsl:when test="$fStrContainsNonZeroDigit=1">1</xsl:when>
1179
+ <xsl:otherwise>0</xsl:otherwise>
1180
+ </xsl:choose>
1181
+ </xsl:otherwise>
1182
+ </xsl:choose>
1183
+ </xsl:template>
1184
+
1185
+
1186
+ <!-- %%Template: match mfrac
1187
+ -->
1188
+ <xsl:template match="mml:mfrac">
1189
+ <xsl:variable name="fBar">
1190
+ <xsl:call-template name="FBar">
1191
+ <xsl:with-param name="sLineThickness">
1192
+ <xsl:choose>
1193
+ <xsl:when test="@linethickness">
1194
+ <xsl:value-of select="@linethickness"/>
1195
+ </xsl:when>
1196
+ <xsl:otherwise>
1197
+ <xsl:value-of select="@mml:linethickness"/>
1198
+ </xsl:otherwise>
1199
+ </xsl:choose>
1200
+ </xsl:with-param>
1201
+ </xsl:call-template>
1202
+ </xsl:variable>
1203
+
1204
+ <xsl:element name="m:f">
1205
+ <xsl:element name="m:fPr">
1206
+ <xsl:element name="m:type">
1207
+ <xsl:attribute name="m:val">
1208
+ <xsl:choose>
1209
+ <xsl:when test="$fBar=0">noBar</xsl:when>
1210
+ <xsl:when test="@bevelled='true' or @mml:bevelled='true'">skw</xsl:when>
1211
+ <xsl:otherwise>bar</xsl:otherwise>
1212
+ </xsl:choose>
1213
+ </xsl:attribute>
1214
+ </xsl:element>
1215
+ </xsl:element>
1216
+ <xsl:element name="m:num">
1217
+ <xsl:call-template name="CreateArgProp" />
1218
+ <xsl:apply-templates select="child::*[1]" />
1219
+ </xsl:element>
1220
+ <xsl:element name="m:den">
1221
+ <xsl:call-template name="CreateArgProp" />
1222
+ <xsl:apply-templates select="child::*[2]" />
1223
+ </xsl:element>
1224
+ </xsl:element>
1225
+ </xsl:template>
1226
+
1227
+ <!-- %%Template: match menclose msqrt
1228
+ -->
1229
+ <xsl:template match="mml:menclose | mml:msqrt">
1230
+ <xsl:variable name="sLowerCaseNotation">
1231
+ <xsl:choose>
1232
+ <xsl:when test="@notation">
1233
+ <xsl:value-of select="translate(@notation, $StrUCAlphabet, $StrLCAlphabet)"/>
1234
+ </xsl:when>
1235
+ <xsl:otherwise>
1236
+ <xsl:value-of select="translate(@mml:notation, $StrUCAlphabet, $StrLCAlphabet)"/>
1237
+ </xsl:otherwise>
1238
+ </xsl:choose>
1239
+ </xsl:variable>
1240
+ <xsl:choose>
1241
+ <!-- Take care of default -->
1242
+ <xsl:when test="$sLowerCaseNotation='radical'
1243
+ or not($sLowerCaseNotation)
1244
+ or $sLowerCaseNotation=''
1245
+ or self::mml:msqrt">
1246
+ <xsl:element name="m:rad">
1247
+ <xsl:element name="m:radPr">
1248
+ <xsl:element name="m:degHide">
1249
+ <xsl:attribute name="m:val">on</xsl:attribute>
1250
+ </xsl:element>
1251
+ </xsl:element>
1252
+ <xsl:element name="m:deg">
1253
+ <xsl:call-template name="CreateArgProp" />
1254
+ </xsl:element>
1255
+ <xsl:element name="m:e">
1256
+ <xsl:call-template name="CreateArgProp" />
1257
+ <xsl:apply-templates select="*" />
1258
+ </xsl:element>
1259
+ </xsl:element>
1260
+ </xsl:when>
1261
+ <xsl:otherwise>
1262
+ <xsl:choose>
1263
+ <xsl:when test="$sLowerCaseNotation='actuarial' or $sLowerCaseNotation='longdiv'" />
1264
+ <xsl:otherwise>
1265
+ <xsl:element name="m:borderBox">
1266
+ <!-- Dealing with more complex notation attribute -->
1267
+ <xsl:variable name="fBox">
1268
+ <xsl:choose>
1269
+ <!-- Word doesn't have circle and roundedbox concepts, therefore, map both to a
1270
+ box. -->
1271
+ <xsl:when test="contains($sLowerCaseNotation, 'box')
1272
+ or contains($sLowerCaseNotation, 'circle')
1273
+ or contains($sLowerCaseNotation, 'roundedbox')">1</xsl:when>
1274
+ <xsl:otherwise>0</xsl:otherwise>
1275
+ </xsl:choose>
1276
+ </xsl:variable>
1277
+ <xsl:variable name="fTop">
1278
+ <xsl:choose>
1279
+ <xsl:when test="contains($sLowerCaseNotation, 'top')">1</xsl:when>
1280
+ <xsl:otherwise>0</xsl:otherwise>
1281
+ </xsl:choose>
1282
+ </xsl:variable>
1283
+ <xsl:variable name="fBot">
1284
+ <xsl:choose>
1285
+ <xsl:when test="contains($sLowerCaseNotation, 'bottom')">1</xsl:when>
1286
+ <xsl:otherwise>0</xsl:otherwise>
1287
+ </xsl:choose>
1288
+ </xsl:variable>
1289
+ <xsl:variable name="fLeft">
1290
+ <xsl:choose>
1291
+ <xsl:when test="contains($sLowerCaseNotation, 'left')">1</xsl:when>
1292
+ <xsl:otherwise>0</xsl:otherwise>
1293
+ </xsl:choose>
1294
+ </xsl:variable>
1295
+ <xsl:variable name="fRight">
1296
+ <xsl:choose>
1297
+ <xsl:when test="contains($sLowerCaseNotation, 'right')">1</xsl:when>
1298
+ <xsl:otherwise>0</xsl:otherwise>
1299
+ </xsl:choose>
1300
+ </xsl:variable>
1301
+ <xsl:variable name="fStrikeH">
1302
+ <xsl:choose>
1303
+ <xsl:when test="contains($sLowerCaseNotation, 'horizontalstrike')">1</xsl:when>
1304
+ <xsl:otherwise>0</xsl:otherwise>
1305
+ </xsl:choose>
1306
+ </xsl:variable>
1307
+ <xsl:variable name="fStrikeV">
1308
+ <xsl:choose>
1309
+ <xsl:when test="contains($sLowerCaseNotation, 'verticalstrike')">1</xsl:when>
1310
+ <xsl:otherwise>0</xsl:otherwise>
1311
+ </xsl:choose>
1312
+ </xsl:variable>
1313
+ <xsl:variable name="fStrikeBLTR">
1314
+ <xsl:choose>
1315
+ <xsl:when test="contains($sLowerCaseNotation, 'updiagonalstrike')">1</xsl:when>
1316
+ <xsl:otherwise>0</xsl:otherwise>
1317
+ </xsl:choose>
1318
+ </xsl:variable>
1319
+ <xsl:variable name="fStrikeTLBR">
1320
+ <xsl:choose>
1321
+ <xsl:when test="contains($sLowerCaseNotation, 'downdiagonalstrike')">1</xsl:when>
1322
+ <xsl:otherwise>0</xsl:otherwise>
1323
+ </xsl:choose>
1324
+ </xsl:variable>
1325
+
1326
+ <!-- Should we create borderBoxPr?
1327
+ We should if the enclosure isn't Word's default, which is
1328
+ a plain box -->
1329
+ <xsl:if test="$fStrikeH=1
1330
+ or $fStrikeV=1
1331
+ or $fStrikeBLTR=1
1332
+ or $fStrikeTLBR=1
1333
+ or ($fBox=0
1334
+ and not($fTop=1
1335
+ and $fBot=1
1336
+ and $fLeft=1
1337
+ and $fRight=1)
1338
+ )">
1339
+ <xsl:element name="m:borderBoxPr">
1340
+ <xsl:if test="$fBox=0">
1341
+ <xsl:if test="$fTop=0">
1342
+ <xsl:element name="m:hideTop">
1343
+ <xsl:attribute name="m:val">on</xsl:attribute>
1344
+ </xsl:element>
1345
+ </xsl:if>
1346
+ <xsl:if test="$fBot=0">
1347
+ <xsl:element name="m:hideBot">
1348
+ <xsl:attribute name="m:val">on</xsl:attribute>
1349
+ </xsl:element>
1350
+ </xsl:if>
1351
+ <xsl:if test="$fLeft=0">
1352
+ <xsl:element name="m:hideLeft">
1353
+ <xsl:attribute name="m:val">on</xsl:attribute>
1354
+ </xsl:element>
1355
+ </xsl:if>
1356
+ <xsl:if test="$fRight=0">
1357
+ <xsl:element name="m:hideRight">
1358
+ <xsl:attribute name="m:val">on</xsl:attribute>
1359
+ </xsl:element>
1360
+ </xsl:if>
1361
+ </xsl:if>
1362
+ <xsl:if test="$fStrikeH=1">
1363
+ <xsl:element name="m:strikeH">
1364
+ <xsl:attribute name="m:val">on</xsl:attribute>
1365
+ </xsl:element>
1366
+ </xsl:if>
1367
+ <xsl:if test="$fStrikeV=1">
1368
+ <xsl:element name="m:strikeV">
1369
+ <xsl:attribute name="m:val">on</xsl:attribute>
1370
+ </xsl:element>
1371
+ </xsl:if>
1372
+ <xsl:if test="$fStrikeBLTR=1">
1373
+ <xsl:element name="m:strikeBLTR">
1374
+ <xsl:attribute name="m:val">on</xsl:attribute>
1375
+ </xsl:element>
1376
+ </xsl:if>
1377
+ <xsl:if test="$fStrikeTLBR=1">
1378
+ <xsl:element name="m:strikeTLBR">
1379
+ <xsl:attribute name="m:val">on</xsl:attribute>
1380
+ </xsl:element>
1381
+ </xsl:if>
1382
+ </xsl:element>
1383
+ </xsl:if>
1384
+ <xsl:element name="m:e">
1385
+ <xsl:call-template name="CreateArgProp" />
1386
+ <xsl:apply-templates select="*" />
1387
+ </xsl:element>
1388
+ </xsl:element>
1389
+ </xsl:otherwise>
1390
+ </xsl:choose>
1391
+ </xsl:otherwise>
1392
+ </xsl:choose>
1393
+ </xsl:template>
1394
+
1395
+ <!-- %%Template: CreateArgProp
1396
+ -->
1397
+ <xsl:template name="CreateArgProp">
1398
+ <xsl:if test="not(count(ancestor-or-self::mml:mstyle[@scriptlevel='0' or @scriptlevel='1' or @scriptlevel='2'])=0)
1399
+ or not(count(ancestor-or-self::mml:mstyle[@mml:scriptlevel='0' or @mml:scriptlevel='1' or @mml:scriptlevel='2'])=0)">
1400
+ <xsl:element name="m:argPr">
1401
+ <xsl:element name="m:scrLvl">
1402
+ <xsl:attribute name="m:val">
1403
+ <xsl:choose>
1404
+ <xsl:when test="ancestor-or-self::mml:mstyle[@scriptlevel][1]/@scriptlevel">
1405
+ <xsl:value-of select="ancestor-or-self::mml:mstyle[@scriptlevel][1]/@scriptlevel"/>
1406
+ </xsl:when>
1407
+ <xsl:otherwise>
1408
+ <xsl:value-of select="ancestor-or-self::mml:mstyle[@scriptlevel][1]/@mml:scriptlevel"/>
1409
+ </xsl:otherwise>
1410
+ </xsl:choose>
1411
+ </xsl:attribute>
1412
+ </xsl:element>
1413
+ </xsl:element>
1414
+ </xsl:if>
1415
+ </xsl:template>
1416
+
1417
+ <!-- %%Template: match mroot
1418
+ -->
1419
+ <xsl:template match="mml:mroot">
1420
+ <xsl:element name="m:rad">
1421
+ <xsl:element name="m:radPr">
1422
+ <xsl:element name="m:degHide">
1423
+ <xsl:attribute name="m:val">off</xsl:attribute>
1424
+ </xsl:element>
1425
+ </xsl:element>
1426
+ <xsl:element name="m:deg">
1427
+ <xsl:call-template name="CreateArgProp" />
1428
+ <xsl:apply-templates select="child::*[2]" />
1429
+ </xsl:element>
1430
+ <xsl:element name="m:e">
1431
+ <xsl:call-template name="CreateArgProp" />
1432
+ <xsl:apply-templates select="child::*[1]" />
1433
+ </xsl:element>
1434
+ </xsl:element>
1435
+ </xsl:template>
1436
+
1437
+ <!-- MathML has no concept of a linear fraction. When transforming a linear fraction
1438
+ from Omml to MathML, we create the following MathML:
1439
+
1440
+ <mml:mrow>
1441
+ <mml:mrow>
1442
+ // numerator
1443
+ </mml:mrow>
1444
+ <mml:mo>/</mml:mo>
1445
+ <mml:mrow>
1446
+ // denominator
1447
+ </mml:mrow>
1448
+ </mml:mrow>
1449
+
1450
+ This template looks for four things:
1451
+ 1. ndCur is an mml:mrow
1452
+ 2. ndCur has three children
1453
+ 3. The second child is an <mml:mo>
1454
+ 4. The second child's text is '/'
1455
+
1456
+ -->
1457
+ <xsl:template name="FLinearFrac">
1458
+ <xsl:param name="ndCur" select="." />
1459
+ <xsl:variable name="sNdText">
1460
+ <xsl:value-of select="normalize-space($ndCur/*[2])"/>
1461
+ </xsl:variable>
1462
+
1463
+ <xsl:choose>
1464
+ <!-- I spy a linear fraction -->
1465
+ <xsl:when test="$ndCur/self::mml:mrow
1466
+ and count($ndCur/*)=3
1467
+ and $ndCur/*[2][self::mml:mo]
1468
+ and $sNdText='/'">1</xsl:when>
1469
+ <xsl:otherwise>0</xsl:otherwise>
1470
+ </xsl:choose>
1471
+ </xsl:template>
1472
+
1473
+
1474
+ <!-- Though presentation mathml can certainly typeset any generic function with the
1475
+ appropriate function operator spacing, presentation MathML has no concept of
1476
+ a function structure like omml does. In order to preserve the omml <func>
1477
+ element, we must establish how an omml <func> element looks in mml. This
1478
+ is shown below:
1479
+
1480
+ <mml:mrow>
1481
+ <mml:mrow>
1482
+ // function name
1483
+ </mml:mrow>
1484
+ <mml:mo>&#x02061;</mml:mo>
1485
+ <mml:mrow>
1486
+ // function argument
1487
+ </mml:mrow>
1488
+ </mml:mrow>
1489
+
1490
+ This template looks for six things to be true:
1491
+ 1. ndCur is an mml:mrow
1492
+ 2. ndCur has three children
1493
+ 3. The first child is an <mml:mrow>
1494
+ 4. The second child is an <mml:mo>
1495
+ 5. The third child is an <mml:mrow>
1496
+ 6. The second child's text is '&#x02061;'
1497
+ -->
1498
+ <xsl:template name="FIsFunc">
1499
+ <xsl:param name="ndCur" select="." />
1500
+ <xsl:variable name="sNdText">
1501
+ <xsl:value-of select="normalize-space($ndCur/*[2])"/>
1502
+ </xsl:variable>
1503
+
1504
+ <xsl:choose>
1505
+ <!-- Is this an omml function -->
1506
+ <xsl:when test="count($ndCur/*)=3
1507
+ and $ndCur/self::*[self::mml:mrow]
1508
+ and $ndCur/*[2][self::mml:mo]
1509
+ and $sNdText='&#x02061;'">1</xsl:when>
1510
+ <xsl:otherwise>0</xsl:otherwise>
1511
+ </xsl:choose>
1512
+ </xsl:template>
1513
+
1514
+
1515
+ <!-- Given the node of the linear fraction's parent mrow,
1516
+ make a linear fraction -->
1517
+ <xsl:template name="MakeLinearFraction">
1518
+ <xsl:param name="ndCur" select="." />
1519
+ <xsl:element name="m:f">
1520
+ <xsl:element name="m:fPr">
1521
+ <xsl:element name="m:type">
1522
+ <xsl:attribute name="m:val">lin</xsl:attribute>
1523
+ </xsl:element>
1524
+ </xsl:element>
1525
+ <xsl:element name="m:num">
1526
+ <xsl:call-template name="CreateArgProp" />
1527
+ <xsl:apply-templates select="$ndCur/*[1]" />
1528
+ </xsl:element>
1529
+ <xsl:element name="m:den">
1530
+ <xsl:call-template name="CreateArgProp" />
1531
+ <xsl:apply-templates select="$ndCur/*[3]" />
1532
+ </xsl:element>
1533
+ </xsl:element>
1534
+ </xsl:template>
1535
+
1536
+
1537
+ <!-- Given the node of the function's parent mrow,
1538
+ make an omml function -->
1539
+ <xsl:template name="WriteFunc">
1540
+ <xsl:param name="ndCur" select="." />
1541
+
1542
+ <xsl:element name="m:func">
1543
+ <xsl:element name="m:fName">
1544
+ <xsl:apply-templates select="$ndCur/child::*[1]" />
1545
+ </xsl:element>
1546
+ <xsl:element name="m:e">
1547
+ <xsl:apply-templates select="$ndCur/child::*[3]" />
1548
+ </xsl:element>
1549
+ </xsl:element>
1550
+ </xsl:template>
1551
+
1552
+
1553
+ <!-- MathML doesn't have the concept of nAry structures. The best approximation
1554
+ to these is to have some under/over or sub/sup followed by an mrow or mstyle.
1555
+
1556
+ In the case that we've come across some under/over or sub/sup that contains an
1557
+ nAry operator, this function handles the following sibling to the nAry structure.
1558
+
1559
+ If the following sibling is:
1560
+
1561
+ mml:mstyle, then apply templates to the children of this mml:mstyle
1562
+
1563
+ mml:mrow, determine if this mrow is a linear fraction
1564
+ (see comments for FlinearFrac template).
1565
+ If so, make an Omml linear fraction.
1566
+ If not, apply templates as was done for mml:mstyle.
1567
+
1568
+ -->
1569
+ <xsl:template name="NaryHandleMrowMstyle">
1570
+ <xsl:param name="ndCur" select="." />
1571
+ <!-- if the next sibling is an mrow, pull it in by
1572
+ doing whatever we would have done to its children.
1573
+ The mrow itself will be skipped, see template above. -->
1574
+ <xsl:choose>
1575
+ <xsl:when test="$ndCur[self::mml:mrow]">
1576
+ <!-- Check for linear fraction -->
1577
+ <xsl:variable name="fLinearFrac">
1578
+ <xsl:call-template name="FLinearFrac">
1579
+ <xsl:with-param name="ndCur" select="$ndCur" />
1580
+ </xsl:call-template>
1581
+ </xsl:variable>
1582
+ <xsl:choose>
1583
+ <xsl:when test="$fLinearFrac=1">
1584
+ <xsl:call-template name="MakeLinearFraction">
1585
+ <xsl:with-param name="ndCur" select="$ndCur" />
1586
+ </xsl:call-template>
1587
+ </xsl:when>
1588
+ <xsl:otherwise>
1589
+ <xsl:variable name="fFunc">
1590
+ <xsl:call-template name="FIsFunc">
1591
+ <xsl:with-param name="ndCur" select="." />
1592
+ </xsl:call-template>
1593
+ </xsl:variable>
1594
+ <xsl:choose>
1595
+ <xsl:when test="$fFunc=1">
1596
+ <xsl:call-template name="WriteFunc">
1597
+ <xsl:with-param name="ndCur" select="." />
1598
+ </xsl:call-template>
1599
+ </xsl:when>
1600
+ <xsl:otherwise>
1601
+ <xsl:apply-templates select="$ndCur/*" />
1602
+ </xsl:otherwise>
1603
+ </xsl:choose>
1604
+ </xsl:otherwise>
1605
+ </xsl:choose>
1606
+ </xsl:when>
1607
+ <xsl:when test="$ndCur[self::mml:mstyle]">
1608
+ <xsl:apply-templates select="$ndCur/*" />
1609
+ </xsl:when>
1610
+ </xsl:choose>
1611
+ </xsl:template>
1612
+
1613
+
1614
+ <!-- MathML munder/mover can represent several Omml constructs
1615
+ (m:bar, m:limLow, m:limUpp, m:acc, m:groupChr, etc.). The following
1616
+ templates (FIsBar, FIsAcc, and FIsGroupChr) are used to determine
1617
+ which of these Omml constructs an munder/mover should be translated into. -->
1618
+
1619
+ <!-- Note: ndCur should only be an munder/mover MathML element.
1620
+
1621
+ ndCur should be interpretted as an m:bar if
1622
+ 1) its respective accent attribute is not true
1623
+ 2) its second child is an mml:mo
1624
+ 3) the character of the mml:mo is the correct under/over bar. -->
1625
+ <xsl:template name="FIsBar">
1626
+ <xsl:param name="ndCur" />
1627
+ <xsl:variable name="fUnder">
1628
+ <xsl:choose>
1629
+ <xsl:when test="$ndCur[self::mml:munder]">1</xsl:when>
1630
+ <xsl:otherwise>0</xsl:otherwise>
1631
+ </xsl:choose>
1632
+ </xsl:variable>
1633
+ <xsl:variable name="sLowerCaseAccent">
1634
+ <xsl:choose>
1635
+ <xsl:when test="$fUnder=1">
1636
+ <xsl:choose>
1637
+ <xsl:when test="$ndCur/@accentunder">
1638
+ <xsl:value-of select="translate($ndCur/@accentunder, $StrUCAlphabet, $StrLCAlphabet)"/>
1639
+ </xsl:when>
1640
+ <xsl:otherwise>
1641
+ <xsl:value-of select="translate($ndCur/@mml:accentunder, $StrUCAlphabet, $StrLCAlphabet)"/>
1642
+ </xsl:otherwise>
1643
+ </xsl:choose>
1644
+ </xsl:when>
1645
+ <xsl:otherwise>
1646
+ <xsl:choose>
1647
+ <xsl:when test="$ndCur/@accent">
1648
+ <xsl:value-of select="translate($ndCur/@accent, $StrUCAlphabet, $StrLCAlphabet)"/>
1649
+ </xsl:when>
1650
+ <xsl:otherwise>
1651
+ <xsl:value-of select="translate($ndCur/@mml:accent, $StrUCAlphabet, $StrLCAlphabet)"/>
1652
+ </xsl:otherwise>
1653
+ </xsl:choose>
1654
+ </xsl:otherwise>
1655
+ </xsl:choose>
1656
+ </xsl:variable>
1657
+ <xsl:variable name="fAccent">
1658
+ <xsl:choose>
1659
+ <xsl:when test="$sLowerCaseAccent='true'">1</xsl:when>
1660
+ <xsl:otherwise>0</xsl:otherwise>
1661
+ </xsl:choose>
1662
+ </xsl:variable>
1663
+
1664
+ <xsl:choose>
1665
+ <!-- The script is unaccented and the second child is an mo -->
1666
+ <xsl:when test="$fAccent = 0
1667
+ and $ndCur/child::*[2]/self::mml:mo">
1668
+ <xsl:variable name="sOperator">
1669
+ <xsl:value-of select="$ndCur/child::*[2]" />
1670
+ </xsl:variable>
1671
+ <xsl:choose>
1672
+ <!-- Should we write an underbar? -->
1673
+ <xsl:when test="$fUnder = 1">
1674
+ <xsl:choose>
1675
+ <xsl:when test="$sOperator = '&#x0332;' or $sOperator = '&#x005F;'">1</xsl:when>
1676
+ <xsl:otherwise>0</xsl:otherwise>
1677
+ </xsl:choose>
1678
+ </xsl:when>
1679
+ <!-- Should we write an overbar? -->
1680
+ <xsl:otherwise>
1681
+ <xsl:choose>
1682
+ <xsl:when test="$sOperator = '&#x0305;' or $sOperator = '&#x00AF;'">1</xsl:when>
1683
+ <xsl:otherwise>0</xsl:otherwise>
1684
+ </xsl:choose>
1685
+ </xsl:otherwise>
1686
+ </xsl:choose>
1687
+ </xsl:when>
1688
+ <xsl:otherwise>0</xsl:otherwise>
1689
+ </xsl:choose>
1690
+ </xsl:template>
1691
+
1692
+ <!-- Note: ndCur should only be an mover MathML element.
1693
+
1694
+ ndCur should be interpretted as an m:acc if
1695
+ 1) its accent attribute is true
1696
+ 2) its second child is an mml:mo
1697
+ 3) there is only zero or one character in the mml:mo -->
1698
+ <xsl:template name="FIsAcc">
1699
+ <xsl:param name="ndCur" select="." />
1700
+
1701
+ <xsl:variable name="sLowerCaseAccent">
1702
+ <xsl:choose>
1703
+ <xsl:when test="$ndCur/@accent">
1704
+ <xsl:value-of select="translate($ndCur/@accent, $StrUCAlphabet, $StrLCAlphabet)"/>
1705
+ </xsl:when>
1706
+ <xsl:otherwise>
1707
+ <xsl:value-of select="translate($ndCur/@mml:accent, $StrUCAlphabet, $StrLCAlphabet)"/>
1708
+ </xsl:otherwise>
1709
+ </xsl:choose>
1710
+ </xsl:variable>
1711
+ <xsl:variable name="sLowerCaseMoAccent">
1712
+ <xsl:choose>
1713
+ <xsl:when test="$ndCur/child::*[2] = mml:mo and $ndCur/child::*[2]/@accent">
1714
+ <xsl:value-of select="translate($ndCur/child::*[2]/@accent, $StrUCAlphabet, $StrLCAlphabet)"/>
1715
+ </xsl:when>
1716
+ <xsl:when test="$ndCur/child::*[2] = mml:mo and $ndCur/child::*[2]/@mml:accent">
1717
+ <xsl:value-of select="translate($ndCur/child::*[2]/@mml:accent, $StrUCAlphabet, $StrLCAlphabet)"/>
1718
+ </xsl:when>
1719
+ </xsl:choose>
1720
+ </xsl:variable>
1721
+ <xsl:variable name="fAccent">
1722
+ <xsl:choose>
1723
+ <xsl:when test="$sLowerCaseMoAccent='true' or ($sLowerCaseMoAccent='' and $sLowerCaseAccent='true')">1</xsl:when>
1724
+ <xsl:otherwise>0</xsl:otherwise>
1725
+ </xsl:choose>
1726
+ </xsl:variable>
1727
+
1728
+ <xsl:choose>
1729
+ <!-- The script is accented and the second child is an mo -->
1730
+ <xsl:when test="$fAccent = 1
1731
+ and $ndCur/child::*[2] = mml:mo">
1732
+ <xsl:variable name="sOperator">
1733
+ <xsl:value-of select="$ndCur/child::*[2]" />
1734
+ </xsl:variable>
1735
+ <xsl:choose>
1736
+ <!-- There is only one operator, this is a valid Omml accent! -->
1737
+ <xsl:when test="string-length($sOperator) &lt;= 1">1</xsl:when>
1738
+ <!-- More than one accented operator. This isn't a valid
1739
+ omml accent -->
1740
+ <xsl:otherwise>0</xsl:otherwise>
1741
+ </xsl:choose>
1742
+ </xsl:when>
1743
+ <!-- Not accented, not an operator, or both, but in any case, this is
1744
+ not an Omml accent. -->
1745
+ <xsl:otherwise>0</xsl:otherwise>
1746
+ </xsl:choose>
1747
+ </xsl:template>
1748
+
1749
+
1750
+ <!-- Is ndCur a groupChr?
1751
+ ndCur is a groupChr if:
1752
+
1753
+ 1. The accent is false (note: accent attribute
1754
+ for munder is accentunder).
1755
+ 2. ndCur is an munder or mover.
1756
+ 3. ndCur has two children
1757
+ 4. Of these two children, one is an mml:mo and the other is an mml:mrow
1758
+ 5. The number of characters in the mml:mo is 1.
1759
+
1760
+ If all of the above are true, then return 1, else return 0.
1761
+ -->
1762
+ <xsl:template name="FIsGroupChr">
1763
+ <xsl:param name="ndCur" select="." />
1764
+ <xsl:variable name="fUnder">
1765
+ <xsl:choose>
1766
+ <xsl:when test="$ndCur[self::mml:munder]">1</xsl:when>
1767
+ <xsl:otherwise>0</xsl:otherwise>
1768
+ </xsl:choose>
1769
+ </xsl:variable>
1770
+ <xsl:variable name="sLowerCaseAccent">
1771
+ <xsl:choose>
1772
+ <xsl:when test="$fUnder=1">
1773
+ <xsl:choose>
1774
+ <xsl:when test="$ndCur/@accentunder">
1775
+ <xsl:value-of select="translate($ndCur/@accentunder, $StrUCAlphabet, $StrLCAlphabet)"/>
1776
+ </xsl:when>
1777
+ <xsl:otherwise>
1778
+ <xsl:value-of select="translate($ndCur/@mml:accentunder, $StrUCAlphabet, $StrLCAlphabet)"/>
1779
+ </xsl:otherwise>
1780
+ </xsl:choose>
1781
+ </xsl:when>
1782
+ <xsl:otherwise>
1783
+ <xsl:choose>
1784
+ <xsl:when test="$ndCur/@accent">
1785
+ <xsl:value-of select="translate($ndCur/@accent, $StrUCAlphabet, $StrLCAlphabet)"/>
1786
+ </xsl:when>
1787
+ <xsl:otherwise>
1788
+ <xsl:value-of select="translate($ndCur/@mml:accent, $StrUCAlphabet, $StrLCAlphabet)"/>
1789
+ </xsl:otherwise>
1790
+ </xsl:choose>
1791
+ </xsl:otherwise>
1792
+ </xsl:choose>
1793
+ </xsl:variable>
1794
+
1795
+ <xsl:variable name="fAccentFalse">
1796
+ <xsl:choose>
1797
+ <xsl:when test="$sLowerCaseAccent='false'">1</xsl:when>
1798
+ <xsl:otherwise>0</xsl:otherwise>
1799
+ </xsl:choose>
1800
+ </xsl:variable>
1801
+
1802
+ <xsl:choose>
1803
+ <xsl:when test="$fAccentFalse=1
1804
+ and $ndCur[self::mml:munder or self::mml:mover]
1805
+ and count($ndCur/child::*)=2
1806
+ and (($ndCur/child::*[1][self::mml:mrow] and $ndCur/child::*[2][self::mml:mo])
1807
+ or ($ndCur/child::*[1][self::mml:mo] and $ndCur/child::*[2][self::mml:mrow]))">
1808
+ <xsl:variable name="sOperator">
1809
+ <xsl:value-of select="$ndCur/child::mml:mo" />
1810
+ </xsl:variable>
1811
+ <xsl:choose>
1812
+ <xsl:when test="string-length($sOperator) &lt;= 1">1</xsl:when>
1813
+ <xsl:otherwise>0</xsl:otherwise>
1814
+ </xsl:choose>
1815
+ </xsl:when>
1816
+
1817
+ <xsl:otherwise>0</xsl:otherwise>
1818
+ </xsl:choose>
1819
+ </xsl:template>
1820
+
1821
+
1822
+ <!-- %%Template: match munder
1823
+ -->
1824
+ <xsl:template match="mml:munder">
1825
+ <xsl:variable name="fNary">
1826
+ <xsl:call-template name="isNary">
1827
+ <xsl:with-param name="ndCur" select="child::*[1]" />
1828
+ </xsl:call-template>
1829
+ </xsl:variable>
1830
+ <xsl:choose>
1831
+ <xsl:when test="$fNary='true'">
1832
+ <m:nary>
1833
+ <xsl:call-template name="CreateNaryProp">
1834
+ <xsl:with-param name="chr">
1835
+ <xsl:value-of select="normalize-space(child::*[1])" />
1836
+ </xsl:with-param>
1837
+ <xsl:with-param name="sMathmlType" select="'munder'" />
1838
+ </xsl:call-template>
1839
+ <m:sub>
1840
+ <xsl:call-template name="CreateArgProp" />
1841
+ <xsl:apply-templates select="child::*[2]" />
1842
+ </m:sub>
1843
+ <m:sup>
1844
+ <xsl:call-template name="CreateArgProp" />
1845
+ </m:sup>
1846
+ <m:e>
1847
+ <xsl:call-template name="CreateArgProp" />
1848
+ <xsl:call-template name="NaryHandleMrowMstyle">
1849
+ <xsl:with-param name="ndCur" select="following-sibling::*[1]" />
1850
+ </xsl:call-template>
1851
+ </m:e>
1852
+ </m:nary>
1853
+ </xsl:when>
1854
+ <xsl:otherwise>
1855
+ <!-- Should this munder be interpreted as an OMML m:bar? -->
1856
+ <xsl:variable name="fIsBar">
1857
+ <xsl:call-template name="FIsBar">
1858
+ <xsl:with-param name="ndCur" select="." />
1859
+ </xsl:call-template>
1860
+ </xsl:variable>
1861
+ <xsl:choose>
1862
+ <xsl:when test="$fIsBar=1">
1863
+ <m:bar>
1864
+ <m:barPr>
1865
+ <m:pos m:val="bot" />
1866
+ </m:barPr>
1867
+ <m:e>
1868
+ <xsl:call-template name="CreateArgProp" />
1869
+ <xsl:apply-templates select="child::*[1]" />
1870
+ </m:e>
1871
+ </m:bar>
1872
+ </xsl:when>
1873
+ <xsl:otherwise>
1874
+ <!-- It isn't an integral or underbar, is this a groupChr? -->
1875
+ <xsl:variable name="fGroupChr">
1876
+ <xsl:call-template name="FIsGroupChr">
1877
+ <xsl:with-param name="ndCur" select="." />
1878
+ </xsl:call-template>
1879
+ </xsl:variable>
1880
+ <xsl:choose>
1881
+ <xsl:when test="$fGroupChr=1">
1882
+ <xsl:element name="m:groupChr">
1883
+ <xsl:call-template name="CreateGroupChrPr">
1884
+ <xsl:with-param name="chr">
1885
+ <xsl:value-of select="mml:mo" />
1886
+ </xsl:with-param>
1887
+ <xsl:with-param name="pos">
1888
+ <xsl:choose>
1889
+ <xsl:when test="child::*[1][self::mml:mrow]">bot</xsl:when>
1890
+ <xsl:otherwise>top</xsl:otherwise>
1891
+ </xsl:choose>
1892
+ </xsl:with-param>
1893
+ <xsl:with-param name="vertJc">top</xsl:with-param>
1894
+ </xsl:call-template>
1895
+ <xsl:element name="m:e">
1896
+ <xsl:apply-templates select="mml:mrow" />
1897
+ </xsl:element>
1898
+ </xsl:element>
1899
+ </xsl:when>
1900
+ <xsl:otherwise>
1901
+ <!-- Generic munder -->
1902
+ <xsl:element name="m:limLow">
1903
+ <xsl:element name="m:e">
1904
+ <xsl:call-template name="CreateArgProp" />
1905
+ <xsl:apply-templates select="child::*[1]" />
1906
+ </xsl:element>
1907
+ <xsl:element name="m:lim">
1908
+ <xsl:call-template name="CreateArgProp" />
1909
+ <xsl:apply-templates select="child::*[2]" />
1910
+ </xsl:element>
1911
+ </xsl:element>
1912
+ </xsl:otherwise>
1913
+ </xsl:choose>
1914
+ </xsl:otherwise>
1915
+ </xsl:choose>
1916
+ </xsl:otherwise>
1917
+ </xsl:choose>
1918
+ </xsl:template>
1919
+
1920
+
1921
+ <!-- Given the values for chr, pos, and vertJc, create an omml
1922
+ groupChr's groupChrPr -->
1923
+ <xsl:template name="CreateGroupChrPr">
1924
+ <xsl:param name="chr">&#x23df;</xsl:param>
1925
+ <xsl:param name="pos" select="bot" />
1926
+ <xsl:param name="vertJc" select="top" />
1927
+ <xsl:element name="m:groupChrPr">
1928
+ <xsl:element name="m:chr">
1929
+ <xsl:attribute name="m:val">
1930
+ <xsl:value-of select="$chr"/>
1931
+ </xsl:attribute>
1932
+ </xsl:element>
1933
+ <xsl:element name="m:pos">
1934
+ <xsl:attribute name="m:val">
1935
+ <xsl:value-of select="$pos"/>
1936
+ </xsl:attribute>
1937
+ </xsl:element>
1938
+ <xsl:element name="m:vertJc">
1939
+ <xsl:attribute name="m:val">
1940
+ <xsl:value-of select="$vertJc"/>
1941
+ </xsl:attribute>
1942
+ </xsl:element>
1943
+ </xsl:element>
1944
+ </xsl:template>
1945
+
1946
+
1947
+ <!--
1948
+ Convert a non-combining character into its upper combining
1949
+ couterpart.
1950
+
1951
+ { Non-combining, Upper-combining }
1952
+ {U+02D8, U+0306}, // BREVE
1953
+ {U+00B8, U+0312}, // CEDILLA
1954
+ {U+0060, U+0300}, // GRAVE ACCENT
1955
+ {U+002D, U+0305}, // HYPHEN-MINUS/OVERLINE
1956
+ {U+2212, U+0305}, // MINUS SIGN/OVERLINE
1957
+ {U+002E, U+0305}, // FULL STOP/DOT ABOVE
1958
+ {U+02D9, U+0307}, // DOT ABOVE
1959
+ {U+02DD, U+030B}, // DOUBLE ACUTE ACCENT
1960
+ {U+00B4, U+0301}, // ACUTE ACCENT
1961
+ {U+007E, U+0303}, // TILDE
1962
+ {U+02DC, U+0303}, // SMALL TILDE
1963
+ {U+00A8, U+0308}, // DIAERESIS
1964
+ {U+02C7, U+030C}, // CARON
1965
+ {U+005E, U+0302}, // CIRCUMFLEX ACCENT
1966
+ {U+00AF, U+0305}, // MACRON
1967
+ {U+005F, ::::::}, // LOW LINE
1968
+ {U+2192, U+20D7}, // RIGHTWARDS ARROW
1969
+ {U+27F6, U+20D7}, // LONG RIGHTWARDS ARROW
1970
+ {U+2190, U+20D6}, // LEFT ARROW
1971
+ -->
1972
+ <xsl:template name="ToUpperCombining">
1973
+ <xsl:param name="ch" />
1974
+ <xsl:choose>
1975
+ <!-- BREVE -->
1976
+ <xsl:when test="$ch='&#x02D8;'">&#x0306;</xsl:when>
1977
+ <!-- CEDILLA -->
1978
+ <xsl:when test="$ch='&#x00B8;'">&#x0312;</xsl:when>
1979
+ <!-- GRAVE ACCENT -->
1980
+ <xsl:when test="$ch='&#x0060;'">&#x0300;</xsl:when>
1981
+ <!-- HYPHEN-MINUS/OVERLINE -->
1982
+ <xsl:when test="$ch='&#x002D;'">&#x0305;</xsl:when>
1983
+ <!-- MINUS SIGN/OVERLINE -->
1984
+ <xsl:when test="$ch='&#x2212;'">&#x0305;</xsl:when>
1985
+ <!-- FULL STOP/DOT ABOVE -->
1986
+ <xsl:when test="$ch='&#x002E;'">&#x0307;</xsl:when>
1987
+ <!-- DOT ABOVE -->
1988
+ <xsl:when test="$ch='&#x02D9;'">&#x0307;</xsl:when>
1989
+ <!-- DOUBLE ACUTE ACCENT -->
1990
+ <xsl:when test="$ch='&#x02DD;'">&#x030B;</xsl:when>
1991
+ <!-- ACUTE ACCENT -->
1992
+ <xsl:when test="$ch='&#x00B4;'">&#x0301;</xsl:when>
1993
+ <!-- TILDE -->
1994
+ <xsl:when test="$ch='&#x007E;'">&#x0303;</xsl:when>
1995
+ <!-- SMALL TILDE -->
1996
+ <xsl:when test="$ch='&#x02DC;'">&#x0303;</xsl:when>
1997
+ <!-- DIAERESIS -->
1998
+ <xsl:when test="$ch='&#x00A8;'">&#x0308;</xsl:when>
1999
+ <!-- CARON -->
2000
+ <xsl:when test="$ch='&#x02C7;'">&#x030C;</xsl:when>
2001
+ <!-- CIRCUMFLEX ACCENT -->
2002
+ <xsl:when test="$ch='&#x005E;'">&#x0302;</xsl:when>
2003
+ <!-- MACRON -->
2004
+ <xsl:when test="$ch='&#x00AF;'">&#x0305;</xsl:when>
2005
+
2006
+ <!-- LOW LINE -->
2007
+
2008
+ <!-- RIGHTWARDS ARROW -->
2009
+ <xsl:when test="$ch='&#x2192;'">&#x20D7;</xsl:when>
2010
+ <!-- LONG RIGHTWARDS ARROW -->
2011
+ <xsl:when test="$ch='&#x27F6;'">&#x20D7;</xsl:when>
2012
+ <!-- LEFT ARROW -->
2013
+ <xsl:when test="$ch='&#x2190;'">&#x20D6;</xsl:when>
2014
+ <xsl:otherwise>
2015
+ <xsl:value-of select="$ch"/>
2016
+ </xsl:otherwise>
2017
+ </xsl:choose>
2018
+ </xsl:template>
2019
+
2020
+
2021
+ <!-- %%Template: match mover
2022
+ -->
2023
+ <xsl:template match="mml:mover">
2024
+ <xsl:variable name="fNary">
2025
+ <xsl:call-template name="isNary">
2026
+ <xsl:with-param name="ndCur" select="child::*[1]" />
2027
+ </xsl:call-template>
2028
+ </xsl:variable>
2029
+ <xsl:choose>
2030
+ <xsl:when test="$fNary='true'">
2031
+ <m:nary>
2032
+ <xsl:call-template name="CreateNaryProp">
2033
+ <xsl:with-param name="chr">
2034
+ <xsl:value-of select="normalize-space(child::*[1])" />
2035
+ </xsl:with-param>
2036
+ <xsl:with-param name="sMathmlType" select="'mover'" />
2037
+ </xsl:call-template>
2038
+ <m:sub>
2039
+ <xsl:call-template name="CreateArgProp" />
2040
+ </m:sub>
2041
+ <m:sup>
2042
+ <xsl:call-template name="CreateArgProp" />
2043
+ <xsl:apply-templates select="child::*[2]" />
2044
+ </m:sup>
2045
+ <m:e>
2046
+ <xsl:call-template name="CreateArgProp" />
2047
+ <xsl:call-template name="NaryHandleMrowMstyle">
2048
+ <xsl:with-param name="ndCur" select="following-sibling::*[1]" />
2049
+ </xsl:call-template>
2050
+ </m:e>
2051
+ </m:nary>
2052
+ </xsl:when>
2053
+ <xsl:otherwise>
2054
+ <!-- Should this munder be interpreted as an OMML m:bar or m:acc? -->
2055
+
2056
+ <!-- Check to see if this is an m:bar -->
2057
+ <xsl:variable name="fIsBar">
2058
+ <xsl:call-template name="FIsBar">
2059
+ <xsl:with-param name="ndCur" select="." />
2060
+ </xsl:call-template>
2061
+ </xsl:variable>
2062
+ <xsl:choose>
2063
+ <xsl:when test="$fIsBar = 1">
2064
+ <m:bar>
2065
+ <m:barPr>
2066
+ <m:pos m:val="top" />
2067
+ </m:barPr>
2068
+ <m:e>
2069
+ <xsl:call-template name="CreateArgProp" />
2070
+ <xsl:apply-templates select="child::*[1]" />
2071
+ </m:e>
2072
+ </m:bar>
2073
+ </xsl:when>
2074
+ <xsl:otherwise>
2075
+ <!-- Not an m:bar, should it be an m:acc? -->
2076
+ <xsl:variable name="fIsAcc">
2077
+ <xsl:call-template name="FIsAcc">
2078
+ <xsl:with-param name="ndCur" select="." />
2079
+ </xsl:call-template>
2080
+ </xsl:variable>
2081
+ <xsl:choose>
2082
+ <xsl:when test="$fIsAcc=1">
2083
+ <m:acc>
2084
+ <m:accPr>
2085
+ <m:chr>
2086
+ <xsl:variable name="ch">
2087
+ <xsl:value-of select="child::*[2]" />
2088
+ </xsl:variable>
2089
+ <xsl:variable name="chComb">
2090
+ <xsl:call-template name="ToUpperCombining">
2091
+ <xsl:with-param name="ch" select="$ch" />
2092
+ </xsl:call-template>
2093
+ </xsl:variable>
2094
+ <xsl:attribute name="m:val">
2095
+ <xsl:value-of select="$chComb" />
2096
+ </xsl:attribute>
2097
+ </m:chr>
2098
+ </m:accPr>
2099
+ <m:e>
2100
+ <xsl:call-template name="CreateArgProp" />
2101
+ <xsl:apply-templates select="child::*[1]" />
2102
+ </m:e>
2103
+ </m:acc>
2104
+ </xsl:when>
2105
+ <xsl:otherwise>
2106
+ <!-- This isn't an integral, overbar or accent,
2107
+ could it be a groupChr? -->
2108
+ <xsl:variable name="fGroupChr">
2109
+ <xsl:call-template name="FIsGroupChr">
2110
+ <xsl:with-param name="ndCur" select="." />
2111
+ </xsl:call-template>
2112
+ </xsl:variable>
2113
+ <xsl:choose>
2114
+ <xsl:when test="$fGroupChr=1">
2115
+ <xsl:element name="m:groupChr">
2116
+ <xsl:call-template name="CreateGroupChrPr">
2117
+ <xsl:with-param name="chr">
2118
+ <xsl:value-of select="mml:mo" />
2119
+ </xsl:with-param>
2120
+ <xsl:with-param name="pos">
2121
+ <xsl:choose>
2122
+ <xsl:when test="child::*[1][self::mml:mrow]">top</xsl:when>
2123
+ <xsl:otherwise>bot</xsl:otherwise>
2124
+ </xsl:choose>
2125
+ </xsl:with-param>
2126
+ <xsl:with-param name="vertJc">bot</xsl:with-param>
2127
+ </xsl:call-template>
2128
+ <xsl:element name="m:e">
2129
+ <xsl:apply-templates select="mml:mrow" />
2130
+ </xsl:element>
2131
+ </xsl:element>
2132
+ </xsl:when>
2133
+ <xsl:otherwise>
2134
+ <!-- Generic mover -->
2135
+ <xsl:element name="m:limUpp">
2136
+ <xsl:element name="m:e">
2137
+ <xsl:call-template name="CreateArgProp" />
2138
+ <xsl:apply-templates select="child::*[1]" />
2139
+ </xsl:element>
2140
+ <xsl:element name="m:lim">
2141
+ <xsl:call-template name="CreateArgProp" />
2142
+ <xsl:apply-templates select="child::*[2]" />
2143
+ </xsl:element>
2144
+ </xsl:element>
2145
+ </xsl:otherwise>
2146
+ </xsl:choose>
2147
+ </xsl:otherwise>
2148
+ </xsl:choose>
2149
+ </xsl:otherwise>
2150
+ </xsl:choose>
2151
+ </xsl:otherwise>
2152
+ </xsl:choose>
2153
+ </xsl:template>
2154
+
2155
+
2156
+ <!-- %%Template: match munderover
2157
+ -->
2158
+ <xsl:template match="mml:munderover">
2159
+ <xsl:variable name="fNary">
2160
+ <xsl:call-template name="isNary">
2161
+ <xsl:with-param name="ndCur" select="child::*[1]" />
2162
+ </xsl:call-template>
2163
+ </xsl:variable>
2164
+ <xsl:choose>
2165
+ <xsl:when test="$fNary='true'">
2166
+ <m:nary>
2167
+ <xsl:call-template name="CreateNaryProp">
2168
+ <xsl:with-param name="chr">
2169
+ <xsl:value-of select="normalize-space(child::*[1])" />
2170
+ </xsl:with-param>
2171
+ <xsl:with-param name="sMathmlType" select="'munderover'" />
2172
+ </xsl:call-template>
2173
+ <m:sub>
2174
+ <xsl:call-template name="CreateArgProp" />
2175
+ <xsl:apply-templates select="child::*[2]" />
2176
+ </m:sub>
2177
+ <m:sup>
2178
+ <xsl:call-template name="CreateArgProp" />
2179
+ <xsl:apply-templates select="child::*[3]" />
2180
+ </m:sup>
2181
+ <m:e>
2182
+ <xsl:call-template name="CreateArgProp" />
2183
+ <xsl:call-template name="NaryHandleMrowMstyle">
2184
+ <xsl:with-param name="ndCur" select="following-sibling::*[1]" />
2185
+ </xsl:call-template>
2186
+ </m:e>
2187
+ </m:nary>
2188
+ </xsl:when>
2189
+ <xsl:otherwise>
2190
+ <xsl:element name="m:limUpp">
2191
+ <xsl:element name="m:e">
2192
+ <xsl:call-template name="CreateArgProp" />
2193
+ <xsl:element name="m:limLow">
2194
+ <xsl:element name="m:e">
2195
+ <xsl:call-template name="CreateArgProp" />
2196
+ <xsl:apply-templates select="child::*[1]" />
2197
+ </xsl:element>
2198
+ <xsl:element name="m:lim">
2199
+ <xsl:call-template name="CreateArgProp" />
2200
+ <xsl:apply-templates select="child::*[2]" />
2201
+ </xsl:element>
2202
+ </xsl:element>
2203
+ </xsl:element>
2204
+ <xsl:element name="m:lim">
2205
+ <xsl:call-template name="CreateArgProp" />
2206
+ <xsl:apply-templates select="child::*[3]" />
2207
+ </xsl:element>
2208
+ </xsl:element>
2209
+ </xsl:otherwise>
2210
+ </xsl:choose>
2211
+ </xsl:template>
2212
+
2213
+ <!-- %%Template: match mfenced -->
2214
+ <xsl:template match="mml:mfenced">
2215
+ <m:d>
2216
+ <xsl:call-template name="CreateDelimProp">
2217
+ <xsl:with-param name="fChOpenValid">
2218
+ <xsl:choose>
2219
+ <xsl:when test="@open">
2220
+ <xsl:value-of select="1"/>
2221
+ </xsl:when>
2222
+ <xsl:when test="@mml:open">
2223
+ <xsl:value-of select="1"/>
2224
+ </xsl:when>
2225
+ <xsl:otherwise>
2226
+ <xsl:value-of select="0"/>
2227
+ </xsl:otherwise>
2228
+ </xsl:choose>
2229
+ </xsl:with-param>
2230
+ <xsl:with-param name="chOpen">
2231
+ <xsl:choose>
2232
+ <xsl:when test="@open">
2233
+ <xsl:value-of select="@open"/>
2234
+ </xsl:when>
2235
+ <xsl:otherwise>
2236
+ <xsl:value-of select="@mml:open"/>
2237
+ </xsl:otherwise>
2238
+ </xsl:choose>
2239
+ </xsl:with-param>
2240
+ <xsl:with-param name="fChSeparatorsValid">
2241
+ <xsl:choose>
2242
+ <xsl:when test="@separators">
2243
+ <xsl:value-of select="1"/>
2244
+ </xsl:when>
2245
+ <xsl:when test="@mml:separators">
2246
+ <xsl:value-of select="1"/>
2247
+ </xsl:when>
2248
+ <xsl:otherwise>
2249
+ <xsl:value-of select="0"/>
2250
+ </xsl:otherwise>
2251
+ </xsl:choose>
2252
+ </xsl:with-param>
2253
+ <xsl:with-param name="chSeparators">
2254
+ <xsl:choose>
2255
+ <xsl:when test="@separators">
2256
+ <xsl:value-of select="@separators"/>
2257
+ </xsl:when>
2258
+ <xsl:otherwise>
2259
+ <xsl:value-of select="@mml:separators"/>
2260
+ </xsl:otherwise>
2261
+ </xsl:choose>
2262
+ </xsl:with-param>
2263
+ <xsl:with-param name="fChCloseValid">
2264
+ <xsl:choose>
2265
+ <xsl:when test="@close">
2266
+ <xsl:value-of select="1"/>
2267
+ </xsl:when>
2268
+ <xsl:when test="@mml:close">
2269
+ <xsl:value-of select="1"/>
2270
+ </xsl:when>
2271
+ <xsl:otherwise>
2272
+ <xsl:value-of select="0"/>
2273
+ </xsl:otherwise>
2274
+ </xsl:choose>
2275
+ </xsl:with-param>
2276
+ <xsl:with-param name="chClose">
2277
+ <xsl:choose>
2278
+ <xsl:when test="@close">
2279
+ <xsl:value-of select="@close"/>
2280
+ </xsl:when>
2281
+ <xsl:otherwise>
2282
+ <xsl:value-of select="@mml:close"/>
2283
+ </xsl:otherwise>
2284
+ </xsl:choose>
2285
+ </xsl:with-param>
2286
+ </xsl:call-template>
2287
+ <xsl:for-each select="*">
2288
+ <m:e>
2289
+ <xsl:call-template name="CreateArgProp" />
2290
+ <xsl:apply-templates select="."/>
2291
+ </m:e>
2292
+ </xsl:for-each>
2293
+ </m:d>
2294
+ </xsl:template>
2295
+
2296
+ <!-- %%Template: CreateDelimProp
2297
+
2298
+ Given the characters to use as open, close and separators for
2299
+ the delim object, create the m:dPr (delim properties).
2300
+
2301
+ MathML can have any number of separators in an mfenced object, but
2302
+ OMML can only represent one separator for each d (delim) object.
2303
+ So, we pick the first separator specified.
2304
+ -->
2305
+ <xsl:template name="CreateDelimProp">
2306
+ <xsl:param name="fChOpenValid" />
2307
+ <xsl:param name="chOpen" />
2308
+ <xsl:param name="fChSeparatorsValid" />
2309
+ <xsl:param name="chSeparators" />
2310
+ <xsl:param name="fChCloseValid" />
2311
+ <xsl:param name="chClose" />
2312
+ <xsl:variable name="chSep" select="substring($chSeparators, 1, 1)" />
2313
+
2314
+ <!-- do we need a dPr at all? If everything's at its default value, then
2315
+ don't bother at all -->
2316
+ <xsl:if test="($fChOpenValid=1 and not($chOpen = '(')) or
2317
+ ($fChCloseValid=1 and not($chClose = ')')) or
2318
+ not($chSep = '|')">
2319
+ <m:dPr>
2320
+ <!-- the default for MathML and OMML is '('. -->
2321
+ <xsl:if test="$fChOpenValid=1 and not($chOpen = '(')">
2322
+ <m:begChr>
2323
+ <xsl:attribute name="m:val">
2324
+ <xsl:value-of select="$chOpen" />
2325
+ </xsl:attribute>
2326
+ </m:begChr>
2327
+ </xsl:if>
2328
+
2329
+ <!-- the default for MathML is ',' and for OMML is '|' -->
2330
+
2331
+ <xsl:choose>
2332
+ <!-- matches OMML's default, don't bother to write anything out -->
2333
+ <xsl:when test="$chSep = '|'" />
2334
+
2335
+ <!-- Not specified, use MathML's default. We test against
2336
+ the existence of the actual attribute, not the substring -->
2337
+ <xsl:when test="$fChSeparatorsValid=0">
2338
+ <m:sepChr m:val=',' />
2339
+ </xsl:when>
2340
+
2341
+ <xsl:otherwise>
2342
+ <m:sepChr>
2343
+ <xsl:attribute name="m:val">
2344
+ <xsl:value-of select="$chSep" />
2345
+ </xsl:attribute>
2346
+ </m:sepChr>
2347
+ </xsl:otherwise>
2348
+ </xsl:choose>
2349
+
2350
+ <!-- the default for MathML and OMML is ')'. -->
2351
+ <xsl:if test="$fChCloseValid=1 and not($chClose = ')')">
2352
+ <m:endChr>
2353
+ <xsl:attribute name="m:val">
2354
+ <xsl:value-of select="$chClose" />
2355
+ </xsl:attribute>
2356
+ </m:endChr>
2357
+ </xsl:if>
2358
+ </m:dPr>
2359
+ </xsl:if>
2360
+ </xsl:template>
2361
+
2362
+ <xsl:template name="LQuoteFromMs">
2363
+ <xsl:param name="msCur" select="." />
2364
+ <xsl:choose>
2365
+ <xsl:when test="(not($msCur/@lquote) or $msCur/@lquote='')
2366
+ and (not($msCur/@mml:lquote) or $msCur/@mml:lquote='')">
2367
+ <xsl:text>"</xsl:text>
2368
+ </xsl:when>
2369
+ <xsl:otherwise>
2370
+ <xsl:choose>
2371
+ <xsl:when test="$msCur/@lquote">
2372
+ <xsl:value-of select="$msCur/@lquote"/>
2373
+ </xsl:when>
2374
+ <xsl:otherwise>
2375
+ <xsl:value-of select="$msCur/@mml:lquote"/>
2376
+ </xsl:otherwise>
2377
+ </xsl:choose>
2378
+ </xsl:otherwise>
2379
+ </xsl:choose>
2380
+ </xsl:template>
2381
+
2382
+ <xsl:template name="RQuoteFromMs">
2383
+ <xsl:param name="msCur" select="." />
2384
+ <xsl:choose>
2385
+ <xsl:when test="(not($msCur/@rquote) or $msCur/@rquote='')
2386
+ and (not($msCur/@mml:rquote) or $msCur/@mml:rquote='')">
2387
+ <xsl:text>"</xsl:text>
2388
+ </xsl:when>
2389
+ <xsl:otherwise>
2390
+ <xsl:choose>
2391
+ <xsl:when test="$msCur/@rquote">
2392
+ <xsl:value-of select="$msCur/@rquote"/>
2393
+ </xsl:when>
2394
+ <xsl:otherwise>
2395
+ <xsl:value-of select="$msCur/@mml:rquote"/>
2396
+ </xsl:otherwise>
2397
+ </xsl:choose>
2398
+ </xsl:otherwise>
2399
+ </xsl:choose>
2400
+ </xsl:template>
2401
+
2402
+ <!-- %%Template: OutputMs
2403
+ -->
2404
+ <xsl:template name="OutputMs">
2405
+ <xsl:param name="msCur" />
2406
+
2407
+ <xsl:variable name="chLquote">
2408
+ <xsl:call-template name="LQuoteFromMs">
2409
+ <xsl:with-param name="msCur" select="$msCur" />
2410
+ </xsl:call-template>
2411
+ </xsl:variable>
2412
+
2413
+ <xsl:variable name="chRquote">
2414
+ <xsl:call-template name="RQuoteFromMs">
2415
+ <xsl:with-param name="msCur" select="$msCur" />
2416
+ </xsl:call-template>
2417
+ </xsl:variable>
2418
+
2419
+ <xsl:value-of select="$chLquote"/>
2420
+ <xsl:value-of select="normalize-space($msCur)" />
2421
+ <xsl:value-of select="$chRquote"/>
2422
+ </xsl:template>
2423
+
2424
+ <!-- %%Template: match msub
2425
+ -->
2426
+ <xsl:template match="mml:msub">
2427
+ <xsl:variable name="fNary">
2428
+ <xsl:call-template name="isNary">
2429
+ <xsl:with-param name="ndCur" select="child::*[1]" />
2430
+ </xsl:call-template>
2431
+ </xsl:variable>
2432
+ <xsl:choose>
2433
+ <xsl:when test="$fNary='true'">
2434
+ <m:nary>
2435
+ <xsl:call-template name="CreateNaryProp">
2436
+ <xsl:with-param name="chr">
2437
+ <xsl:value-of select="normalize-space(child::*[1])" />
2438
+ </xsl:with-param>
2439
+ <xsl:with-param name="sMathmlType" select="'msub'" />
2440
+ </xsl:call-template>
2441
+ <m:sub>
2442
+ <xsl:call-template name="CreateArgProp" />
2443
+ <xsl:apply-templates select="child::*[2]" />
2444
+ </m:sub>
2445
+ <m:sup>
2446
+ <xsl:call-template name="CreateArgProp" />
2447
+ </m:sup>
2448
+ <m:e>
2449
+ <xsl:call-template name="CreateArgProp" />
2450
+ <xsl:call-template name="NaryHandleMrowMstyle">
2451
+ <xsl:with-param name="ndCur" select="following-sibling::*[1]" />
2452
+ </xsl:call-template>
2453
+ </m:e>
2454
+ </m:nary>
2455
+ </xsl:when>
2456
+ <xsl:otherwise>
2457
+ <m:sSub>
2458
+ <m:e>
2459
+ <xsl:call-template name="CreateArgProp" />
2460
+ <xsl:apply-templates select="child::*[1]" />
2461
+ </m:e>
2462
+ <m:sub>
2463
+ <xsl:call-template name="CreateArgProp" />
2464
+ <xsl:apply-templates select="child::*[2]" />
2465
+ </m:sub>
2466
+ </m:sSub>
2467
+ </xsl:otherwise>
2468
+ </xsl:choose>
2469
+ </xsl:template>
2470
+
2471
+ <!-- %%Template: match msup
2472
+ -->
2473
+ <xsl:template match="mml:msup">
2474
+ <xsl:variable name="fNary">
2475
+ <xsl:call-template name="isNary">
2476
+ <xsl:with-param name="ndCur" select="child::*[1]" />
2477
+ </xsl:call-template>
2478
+ </xsl:variable>
2479
+ <xsl:choose>
2480
+ <xsl:when test="$fNary='true'">
2481
+ <m:nary>
2482
+ <xsl:call-template name="CreateNaryProp">
2483
+ <xsl:with-param name="chr">
2484
+ <xsl:value-of select="normalize-space(child::*[1])" />
2485
+ </xsl:with-param>
2486
+ <xsl:with-param name="sMathmlType" select="'msup'" />
2487
+ </xsl:call-template>
2488
+ <m:sub>
2489
+ <xsl:call-template name="CreateArgProp" />
2490
+ </m:sub>
2491
+ <m:sup>
2492
+ <xsl:call-template name="CreateArgProp" />
2493
+ <xsl:apply-templates select="child::*[2]" />
2494
+ </m:sup>
2495
+ <m:e>
2496
+ <xsl:call-template name="CreateArgProp" />
2497
+ <xsl:call-template name="NaryHandleMrowMstyle">
2498
+ <xsl:with-param name="ndCur" select="following-sibling::*[1]" />
2499
+ </xsl:call-template>
2500
+ </m:e>
2501
+ </m:nary>
2502
+ </xsl:when>
2503
+ <xsl:otherwise>
2504
+ <m:sSup>
2505
+ <m:e>
2506
+ <xsl:call-template name="CreateArgProp" />
2507
+ <xsl:apply-templates select="child::*[1]" />
2508
+ </m:e>
2509
+ <m:sup>
2510
+ <xsl:call-template name="CreateArgProp" />
2511
+ <xsl:apply-templates select="child::*[2]" />
2512
+ </m:sup>
2513
+ </m:sSup>
2514
+ </xsl:otherwise>
2515
+ </xsl:choose>
2516
+ </xsl:template>
2517
+
2518
+ <!-- %%Template: match msubsup
2519
+ -->
2520
+ <xsl:template match="mml:msubsup">
2521
+ <xsl:variable name="fNary">
2522
+ <xsl:call-template name="isNary">
2523
+ <xsl:with-param name="ndCur" select="child::*[1]" />
2524
+ </xsl:call-template>
2525
+ </xsl:variable>
2526
+ <xsl:choose>
2527
+ <xsl:when test="$fNary='true'">
2528
+ <m:nary>
2529
+ <xsl:call-template name="CreateNaryProp">
2530
+ <xsl:with-param name="chr">
2531
+ <xsl:value-of select="normalize-space(child::*[1])" />
2532
+ </xsl:with-param>
2533
+ <xsl:with-param name="sMathmlType" select="'msubsup'" />
2534
+ </xsl:call-template>
2535
+ <m:sub>
2536
+ <xsl:call-template name="CreateArgProp" />
2537
+ <xsl:apply-templates select="child::*[2]" />
2538
+ </m:sub>
2539
+ <m:sup>
2540
+ <xsl:call-template name="CreateArgProp" />
2541
+ <xsl:apply-templates select="child::*[3]" />
2542
+ </m:sup>
2543
+ <m:e>
2544
+ <xsl:call-template name="CreateArgProp" />
2545
+ <xsl:call-template name="NaryHandleMrowMstyle">
2546
+ <xsl:with-param name="ndCur" select="following-sibling::*[1]" />
2547
+ </xsl:call-template>
2548
+ </m:e>
2549
+ </m:nary>
2550
+ </xsl:when>
2551
+ <xsl:otherwise>
2552
+ <m:sSubSup>
2553
+ <m:e>
2554
+ <xsl:call-template name="CreateArgProp" />
2555
+ <xsl:apply-templates select="child::*[1]" />
2556
+ </m:e>
2557
+ <m:sub>
2558
+ <xsl:call-template name="CreateArgProp" />
2559
+ <xsl:apply-templates select="child::*[2]" />
2560
+ </m:sub>
2561
+ <m:sup>
2562
+ <xsl:call-template name="CreateArgProp" />
2563
+ <xsl:apply-templates select="child::*[3]" />
2564
+ </m:sup>
2565
+ </m:sSubSup>
2566
+ </xsl:otherwise>
2567
+ </xsl:choose>
2568
+ </xsl:template>
2569
+
2570
+ <!-- %%Template: SplitScripts
2571
+
2572
+ Takes an collection of nodes, and splits them
2573
+ odd and even into sup and sub scripts. Used for dealing with
2574
+ mmultiscript.
2575
+
2576
+ This template assumes you want to output both a sub and sup element.
2577
+ -->
2578
+ <xsl:template name="SplitScripts">
2579
+ <xsl:param name="ndScripts" />
2580
+ <m:sub>
2581
+ <xsl:call-template name="CreateArgProp" />
2582
+ <xsl:apply-templates select="$ndScripts[(position() mod 2) = 1]" />
2583
+ </m:sub>
2584
+ <m:sup>
2585
+ <xsl:call-template name="CreateArgProp" />
2586
+ <xsl:apply-templates select="$ndScripts[(position() mod 2) = 0]" />
2587
+ </m:sup>
2588
+ </xsl:template>
2589
+
2590
+ <!-- %%Template: match mmultiscripts
2591
+
2592
+ There is some subtlety with the mml:mprescripts element. Everything that comes before
2593
+ that is considered a script (as opposed to a pre-script), but it need not be present.
2594
+ -->
2595
+ <xsl:template match="mml:mmultiscripts">
2596
+
2597
+ <!-- count the nodes. Everything that comes after a mml:mprescripts is considered a pre-script;
2598
+ Everything that does not have an mml:mprescript as a preceding-sibling (and is not itself
2599
+ mml:mprescript) is a script, except for the first child which is always the base.
2600
+ The mml:none element is a place holder for a sub/sup element slot.
2601
+
2602
+ mmultisript pattern:
2603
+ <mmultiscript>
2604
+ (base)
2605
+ (sub sup)* // Where <none/> can replace a sub/sup entry to preserve pattern.
2606
+ <mprescripts />
2607
+ (presub presup)*
2608
+ </mmultiscript>
2609
+ -->
2610
+ <!-- Count of presecript nodes that we'd print (this is essentially anything but the none placeholder. -->
2611
+ <xsl:variable name="cndPrescriptStrict" select="count(mml:mprescripts[1]/following-sibling::*[not(self::mml:none)])" />
2612
+ <!-- Count of all super script excluding mml:none -->
2613
+ <xsl:variable name="cndSuperScript" select="count(*[not(preceding-sibling::mml:mprescripts)
2614
+ and not(self::mml:mprescripts)
2615
+ and ((position() mod 2) = 1)
2616
+ and not(self::mml:none)]) - 1"/>
2617
+ <!-- Count of all sup script excluding mml:none -->
2618
+ <xsl:variable name="cndSubScript" select="count(*[not(preceding-sibling::mml:mprescripts)
2619
+ and not(self::mml:mprescripts)
2620
+ and ((position() mod 2) = 0)
2621
+ and not(self::mml:none)])"/>
2622
+ <!-- Count of all scripts excluding mml:none -->
2623
+ <xsl:variable name="cndScriptStrict" select="$cndSuperScript + $cndSubScript" />
2624
+ <!-- Count of all scripts including mml:none. This is essentially all nodes before the
2625
+ first mml:mprescripts except the base. -->
2626
+ <xsl:variable name="cndScript" select="count(*[not(preceding-sibling::mml:mprescripts) and not(self::mml:mprescripts)]) - 1" />
2627
+
2628
+ <xsl:choose>
2629
+ <!-- The easy case first. No prescripts, and no script ... just a base -->
2630
+ <xsl:when test="$cndPrescriptStrict &lt;= 0 and $cndScriptStrict &lt;= 0">
2631
+ <xsl:apply-templates select="*[1]" />
2632
+ </xsl:when>
2633
+
2634
+ <!-- Next, if there are no prescripts -->
2635
+ <xsl:when test="$cndPrescriptStrict &lt;= 0">
2636
+ <!-- we know we have some scripts or else we would have taken the earlier
2637
+ branch. -->
2638
+ <xsl:choose>
2639
+ <!-- We have both sub and super scripts-->
2640
+ <xsl:when test="$cndSuperScript &gt; 0 and $cndSubScript &gt; 0">
2641
+ <m:sSubSup>
2642
+ <m:e>
2643
+ <xsl:call-template name="CreateArgProp" />
2644
+ <xsl:apply-templates select="child::*[1]" />
2645
+ </m:e>
2646
+
2647
+ <!-- Every child except the first is a script. Do the split -->
2648
+ <xsl:call-template name="SplitScripts">
2649
+ <xsl:with-param name="ndScripts" select="*[position() &gt; 1]" />
2650
+ </xsl:call-template>
2651
+ </m:sSubSup>
2652
+ </xsl:when>
2653
+ <!-- Just a sub script -->
2654
+ <xsl:when test="$cndSubScript &gt; 0">
2655
+ <m:sSub>
2656
+ <m:e>
2657
+ <xsl:call-template name="CreateArgProp" />
2658
+ <xsl:apply-templates select="child::*[1]" />
2659
+ </m:e>
2660
+
2661
+ <!-- No prescripts and no super scripts, therefore, it's a sub. -->
2662
+ <m:sub>
2663
+ <xsl:apply-templates select="*[position() &gt; 1]" />
2664
+ </m:sub>
2665
+ </m:sSub>
2666
+ </xsl:when>
2667
+ <!-- Just super script -->
2668
+ <xsl:otherwise>
2669
+ <m:sSup>
2670
+ <m:e>
2671
+ <xsl:call-template name="CreateArgProp" />
2672
+ <xsl:apply-templates select="child::*[1]" />
2673
+ </m:e>
2674
+
2675
+ <!-- No prescripts and no sub scripts, therefore, it's a sup. -->
2676
+ <m:sup>
2677
+ <xsl:apply-templates select="*[position() &gt; 1]" />
2678
+ </m:sup>
2679
+ </m:sSup>
2680
+ </xsl:otherwise>
2681
+ </xsl:choose>
2682
+ </xsl:when>
2683
+
2684
+ <!-- Next, if there are no scripts -->
2685
+ <xsl:when test="$cndScriptStrict &lt;= 0">
2686
+ <!-- we know we have some prescripts or else we would have taken the earlier
2687
+ branch. So, create an sPre and split the elements -->
2688
+ <m:sPre>
2689
+ <m:e>
2690
+ <xsl:call-template name="CreateArgProp" />
2691
+ <xsl:apply-templates select="child::*[1]" />
2692
+ </m:e>
2693
+
2694
+ <!-- The prescripts come after the mml:mprescript and if we get here
2695
+ we know there exists some elements after the mml:mprescript element.
2696
+
2697
+ The prescript element has no sub/subsup variation, therefore, even if
2698
+ we're only writing sub, we need to write out both the sub and sup element.
2699
+ -->
2700
+ <xsl:call-template name="SplitScripts">
2701
+ <xsl:with-param name="ndScripts" select="mml:mprescripts[1]/following-sibling::*" />
2702
+ </xsl:call-template>
2703
+ </m:sPre>
2704
+ </xsl:when>
2705
+
2706
+ <!-- Finally, the case with both prescripts and scripts. Create an sPre
2707
+ element to house the prescripts, with a sub/sup/subsup element at its base. -->
2708
+ <xsl:otherwise>
2709
+ <m:sPre>
2710
+ <m:e>
2711
+ <xsl:choose>
2712
+ <!-- We have both sub and super scripts-->
2713
+ <xsl:when test="$cndSuperScript &gt; 0 and $cndSubScript &gt; 0">
2714
+ <m:sSubSup>
2715
+ <m:e>
2716
+ <xsl:call-template name="CreateArgProp" />
2717
+ <xsl:apply-templates select="child::*[1]" />
2718
+ </m:e>
2719
+
2720
+ <!-- scripts come before the mml:mprescript but after the first child, so their
2721
+ positions will be 2, 3, ... ($nndScript + 1) -->
2722
+ <xsl:call-template name="SplitScripts">
2723
+ <xsl:with-param name="ndScripts" select="*[(position() &gt; 1) and (position() &lt;= ($cndScript + 1))]" />
2724
+ </xsl:call-template>
2725
+ </m:sSubSup>
2726
+ </xsl:when>
2727
+ <!-- Just a sub script -->
2728
+ <xsl:when test="$cndSubScript &gt; 0">
2729
+ <m:sSub>
2730
+ <m:e>
2731
+ <xsl:call-template name="CreateArgProp" />
2732
+ <xsl:apply-templates select="child::*[1]" />
2733
+ </m:e>
2734
+
2735
+ <!-- We have prescripts but no super scripts, therefore, do a sub
2736
+ and apply templates to all tokens counted by cndScript. -->
2737
+ <m:sub>
2738
+ <xsl:apply-templates select="*[position() &gt; 1 and (position() &lt;= ($cndScript + 1))]" />
2739
+ </m:sub>
2740
+ </m:sSub>
2741
+ </xsl:when>
2742
+ <!-- Just super script -->
2743
+ <xsl:otherwise>
2744
+ <m:sSup>
2745
+ <m:e>
2746
+ <xsl:call-template name="CreateArgProp" />
2747
+ <xsl:apply-templates select="child::*[1]" />
2748
+ </m:e>
2749
+
2750
+ <!-- We have prescripts but no sub scripts, therefore, do a sub
2751
+ and apply templates to all tokens counted by cndScript. -->
2752
+ <m:sup>
2753
+ <xsl:apply-templates select="*[position() &gt; 1 and (position() &lt;= ($cndScript + 1))]" />
2754
+ </m:sup>
2755
+ </m:sSup>
2756
+ </xsl:otherwise>
2757
+ </xsl:choose>
2758
+ </m:e>
2759
+
2760
+ <!-- The prescripts come after the mml:mprescript and if we get here
2761
+ we know there exists one such element -->
2762
+ <xsl:call-template name="SplitScripts">
2763
+ <xsl:with-param name="ndScripts" select="mml:mprescripts[1]/following-sibling::*" />
2764
+ </xsl:call-template>
2765
+ </m:sPre>
2766
+ </xsl:otherwise>
2767
+ </xsl:choose>
2768
+ </xsl:template>
2769
+
2770
+ <!-- Template that determines if ndCur is an equation array.
2771
+
2772
+ ndCur is an equation array if:
2773
+
2774
+ 1. There are are no frame lines
2775
+ 2. There are no column lines
2776
+ 3. There are no row lines
2777
+ 4. There is no row with more than 1 column
2778
+ 5. There is no row with fewer than 1 column
2779
+ 6. There are no labeled rows.
2780
+
2781
+ -->
2782
+ <xsl:template name="FIsEqArray">
2783
+ <xsl:param name="ndCur" select="." />
2784
+
2785
+ <!-- There should be no frame, columnlines, or rowlines -->
2786
+ <xsl:choose>
2787
+ <xsl:when test="(not($ndCur/@frame) or $ndCur/@frame='' or $ndCur/@frame='none')
2788
+ and (not($ndCur/@mml:frame) or $ndCur/@mml:frame='' or $ndCur/@mml:frame='none')
2789
+ and (not($ndCur/@columnlines) or $ndCur/@columnlines='' or $ndCur/@columnlines='none')
2790
+ and (not($ndCur/@mml:columnlines) or $ndCur/@mml:columnlines='' or $ndCur/@mml:columnlines='none')
2791
+ and (not($ndCur/@rowlines) or $ndCur/@rowlines='' or $ndCur/@rowlines='none')
2792
+ and (not($ndCur/@mml:rowlines) or $ndCur/@mml:rowlines='' or $ndCur/@mml:rowlines='none')
2793
+ and not($ndCur/mml:mtr[count(mml:mtd) &gt; 1])
2794
+ and not($ndCur/mml:mtr[count(mml:mtd) &lt; 1])
2795
+ and not($ndCur/mml:mlabeledtr)">1</xsl:when>
2796
+ <xsl:otherwise>0</xsl:otherwise>
2797
+ </xsl:choose>
2798
+ </xsl:template>
2799
+
2800
+ <!-- Template used to determine if we should ignore a collection when iterating through
2801
+ a mathml equation array row.
2802
+
2803
+ So far, the only thing that needs to be ignored is the argument of an nary. We
2804
+ can ignore this since it is output when we apply-templates to the munder[over]/msub[sup].
2805
+ -->
2806
+ <xsl:template name="FIgnoreCollection">
2807
+ <xsl:param name="ndCur" select="." />
2808
+
2809
+ <xsl:variable name="fNaryArgument">
2810
+ <xsl:call-template name="FIsNaryArgument">
2811
+ <xsl:with-param name="ndCur" select="$ndCur" />
2812
+ </xsl:call-template>
2813
+ </xsl:variable>
2814
+
2815
+ <xsl:choose>
2816
+ <xsl:when test="$fNaryArgument=1">1</xsl:when>
2817
+ <xsl:otherwise>0</xsl:otherwise>
2818
+ </xsl:choose>
2819
+ </xsl:template>
2820
+
2821
+ <!-- Template used to determine if we've already encountered an maligngroup or malignmark.
2822
+
2823
+ This is needed because omml has an implicit spacing alignment (omml spacing alignment =
2824
+ mathml's maligngroup element) at the beginning of each equation array row. Therefore,
2825
+ the first maligngroup (implied or explicit) we encounter does not need to be output.
2826
+ This template recursively searches up the xml tree and looks at previous siblings to see
2827
+ if they have a descendant that is an maligngroup or malignmark. We look for the malignmark
2828
+ to find the implicit maligngroup.
2829
+ -->
2830
+ <xsl:template name="FFirstAlignAlreadyFound">
2831
+ <xsl:param name="ndCur" select="." />
2832
+
2833
+ <xsl:choose>
2834
+ <xsl:when test="count($ndCur/preceding-sibling::*[descendant-or-self::mml:maligngroup
2835
+ or descendant-or-self::mml:malignmark]) &gt; 0">1</xsl:when>
2836
+ <xsl:when test="not($ndCur/parent::mml:mtd)">
2837
+ <xsl:call-template name="FFirstAlignAlreadyFound">
2838
+ <xsl:with-param name="ndCur" select="$ndCur/parent::*" />
2839
+ </xsl:call-template>
2840
+ </xsl:when>
2841
+ <xsl:otherwise>0</xsl:otherwise>
2842
+ </xsl:choose>
2843
+ </xsl:template>
2844
+
2845
+ <!-- This template builds a string that is result of concatenating a given string several times.
2846
+
2847
+ Given strToRepeat, create a string that has strToRepeat repeated iRepitions times.
2848
+ -->
2849
+ <xsl:template name="ConcatStringRepeat">
2850
+ <xsl:param name="strToRepeat" select="''" />
2851
+ <xsl:param name="iRepetitions" select="0" />
2852
+ <xsl:param name="strBuilding" select="''" />
2853
+
2854
+ <xsl:choose>
2855
+ <xsl:when test="$iRepetitions &lt;= 0">
2856
+ <xsl:value-of select="$strBuilding" />
2857
+ </xsl:when>
2858
+ <xsl:otherwise>
2859
+ <xsl:call-template name="ConcatStringRepeat">
2860
+ <xsl:with-param name="strToRepeat" select="$strToRepeat" />
2861
+ <xsl:with-param name="iRepetitions" select="$iRepetitions - 1" />
2862
+ <xsl:with-param name="strBuilding" select="concat($strBuilding, $strToRepeat)" />
2863
+ </xsl:call-template>
2864
+ </xsl:otherwise>
2865
+ </xsl:choose>
2866
+ </xsl:template>
2867
+
2868
+ <!-- This template determines if ndCur is a special collection.
2869
+ By special collection, I mean is ndCur the outer element of some special grouping
2870
+ of mathml elements that actually represents some over all omml structure.
2871
+
2872
+ For instance, is ndCur a linear fraction, or an omml function.
2873
+ -->
2874
+ <xsl:template name="FSpecialCollection">
2875
+ <xsl:param name="ndCur" select="." />
2876
+ <xsl:choose>
2877
+ <xsl:when test="$ndCur/self::mml:mrow">
2878
+ <xsl:variable name="fLinearFraction">
2879
+ <xsl:call-template name="FLinearFrac">
2880
+ <xsl:with-param name="ndCur" select="$ndCur"/>
2881
+ </xsl:call-template>
2882
+ </xsl:variable>
2883
+ <xsl:variable name="fFunc">
2884
+ <xsl:call-template name="FIsFunc">
2885
+ <xsl:with-param name="ndCur" select="$ndCur" />
2886
+ </xsl:call-template>
2887
+ </xsl:variable>
2888
+ <xsl:choose>
2889
+ <xsl:when test="$fLinearFraction=1 or $fFunc=1">1</xsl:when>
2890
+ <xsl:otherwise>0</xsl:otherwise>
2891
+ </xsl:choose>
2892
+ </xsl:when>
2893
+ <xsl:otherwise>0</xsl:otherwise>
2894
+ </xsl:choose>
2895
+ </xsl:template>
2896
+
2897
+ <!-- This template iterates through the children of an equation array row (mtr) and outputs
2898
+ the equation.
2899
+
2900
+ This template does all the work to output ampersands and skip the right elements when needed.
2901
+ -->
2902
+ <xsl:template name="ProcessEqArrayRow">
2903
+ <xsl:param name="ndCur" select="." />
2904
+
2905
+ <xsl:for-each select="$ndCur/*">
2906
+ <xsl:variable name="fSpecialCollection">
2907
+ <xsl:call-template name="FSpecialCollection">
2908
+ <xsl:with-param name="ndCur" select="." />
2909
+ </xsl:call-template>
2910
+ </xsl:variable>
2911
+ <xsl:variable name="fIgnoreCollection">
2912
+ <xsl:call-template name="FIgnoreCollection">
2913
+ <xsl:with-param name="ndCur" select="." />
2914
+ </xsl:call-template>
2915
+ </xsl:variable>
2916
+ <xsl:choose>
2917
+ <!-- If we have an alignment element output the ampersand. -->
2918
+ <xsl:when test="self::mml:maligngroup or self::mml:malignmark">
2919
+ <!-- Omml has an implied spacing alignment at the beginning of each equation.
2920
+ Therefore, if this is the first ampersand to be output, don't actually output. -->
2921
+ <xsl:variable name="fFirstAlignAlreadyFound">
2922
+ <xsl:call-template name="FFirstAlignAlreadyFound">
2923
+ <xsl:with-param name="ndCur" select="." />
2924
+ </xsl:call-template>
2925
+ </xsl:variable>
2926
+ <!-- Don't output unless it is an malignmark or we have already previously found an alignment point. -->
2927
+ <xsl:if test="self::mml:malignmark or $fFirstAlignAlreadyFound=1">
2928
+ <m:r>
2929
+ <m:t>&amp;</m:t>
2930
+ </m:r>
2931
+ </xsl:if>
2932
+ </xsl:when>
2933
+ <!-- If this node is an non-special mrow or mstyle and we aren't supposed to ignore this collection, then
2934
+ go ahead an apply templates to this node. -->
2935
+ <xsl:when test="$fIgnoreCollection=0 and ((self::mml:mrow and $fSpecialCollection=0) or self::mml:mstyle)">
2936
+ <xsl:call-template name="ProcessEqArrayRow">
2937
+ <xsl:with-param name="ndCur" select="." />
2938
+ </xsl:call-template>
2939
+ </xsl:when>
2940
+ <!-- At this point we have some mathml structure (fraction, nary, non-grouping element, etc.) -->
2941
+ <!-- If this mathml structure has alignment groups or marks as children, then extract those since
2942
+ omml can't handle that. -->
2943
+ <xsl:when test="descendant::mml:maligngroup or descendant::mml:malignmark">
2944
+ <xsl:variable name="cMalignGroups">
2945
+ <xsl:value-of select="count(descendant::mml:maligngroup)" />
2946
+ </xsl:variable>
2947
+ <xsl:variable name="cMalignMarks">
2948
+ <xsl:value-of select="count(descendant::mml:malignmark)" />
2949
+ </xsl:variable>
2950
+ <!-- Output all maligngroups and malignmarks as '&' -->
2951
+ <xsl:if test="$cMalignGroups + $cMalignMarks &gt; 0">
2952
+ <xsl:variable name="str">
2953
+ <xsl:call-template name="ConcatStringRepeat">
2954
+ <xsl:with-param name="strToRepeat" select="'&amp;'" />
2955
+ <xsl:with-param name="iRepetitions" select="$cMalignGroups + $cMalignMarks" />
2956
+ <xsl:with-param name="strBuilding" select="''" />
2957
+ </xsl:call-template>
2958
+ </xsl:variable>
2959
+ <xsl:element name="m:r">
2960
+ <xsl:element name="m:t">
2961
+ <xsl:call-template name="OutputText">
2962
+ <xsl:with-param name="sInput" select="$str" />
2963
+ </xsl:call-template>
2964
+ </xsl:element>
2965
+ </xsl:element>
2966
+ </xsl:if>
2967
+ <!-- Now that the '&' have been extracted, just apply-templates to this node.-->
2968
+ <xsl:apply-templates select="." />
2969
+ </xsl:when>
2970
+ <!-- If there are no alignment points as descendants, then go ahead and output this node. -->
2971
+ <xsl:otherwise>
2972
+ <xsl:apply-templates select="." />
2973
+ </xsl:otherwise>
2974
+ </xsl:choose>
2975
+ </xsl:for-each>
2976
+ </xsl:template>
2977
+
2978
+ <!-- This template transforms mtable into its appropriate omml type.
2979
+
2980
+ There are two possible omml constructs that an mtable can become: a matrix or
2981
+ an equation array.
2982
+
2983
+ Because omml has no generic table construct, the omml matrix is the best approximate
2984
+ for a mathml table.
2985
+
2986
+ Our equation array transformation is very simple. The main goal of this transform is to
2987
+ allow roundtripping omml eq arrays through mathml. The template ProcessEqArrayRow was never
2988
+ intended to account for many of the alignment flexibilities that are present in mathml like
2989
+ using the alig attribute, using alignmark attribute in token elements, etc.
2990
+
2991
+ The restrictions on this transform require <malignmark> and <maligngroup> elements to be outside of
2992
+ any non-grouping mathml elements (that is, mrow and mstyle). Moreover, these elements cannot be the children of
2993
+ mrows that represent linear fractions or functions. Also, <malignmark> cannot be a child
2994
+ of token attributes.
2995
+
2996
+ In the case that the above
2997
+
2998
+ -->
2999
+ <xsl:template match="mml:mtable">
3000
+ <xsl:variable name="fEqArray">
3001
+ <xsl:call-template name="FIsEqArray">
3002
+ <xsl:with-param name="ndCur" select="." />
3003
+ </xsl:call-template>
3004
+ </xsl:variable>
3005
+ <xsl:choose>
3006
+ <xsl:when test="$fEqArray=1">
3007
+ <xsl:element name="m:eqArr">
3008
+ <xsl:for-each select="mml:mtr">
3009
+ <xsl:element name="m:e">
3010
+ <xsl:call-template name="ProcessEqArrayRow">
3011
+ <xsl:with-param name="ndCur" select="mml:mtd" />
3012
+ </xsl:call-template>
3013
+ </xsl:element>
3014
+ </xsl:for-each>
3015
+ </xsl:element>
3016
+ </xsl:when>
3017
+ <xsl:otherwise>
3018
+ <xsl:variable name="cMaxElmtsInRow">
3019
+ <xsl:call-template name="CountMaxElmtsInRow">
3020
+ <xsl:with-param name="ndCur" select="*[1]" />
3021
+ <xsl:with-param name="cMaxElmtsInRow" select="0" />
3022
+ </xsl:call-template>
3023
+ </xsl:variable>
3024
+ <m:m>
3025
+ <m:mPr>
3026
+ <m:baseJc m:val="center" />
3027
+ <m:plcHide m:val="on" />
3028
+ <m:mcs>
3029
+ <m:mc>
3030
+ <m:mcPr>
3031
+ <m:count>
3032
+ <xsl:attribute name="m:val">
3033
+ <xsl:value-of select="$cMaxElmtsInRow" />
3034
+ </xsl:attribute>
3035
+ </m:count>
3036
+ <m:mcJc m:val="center" />
3037
+ </m:mcPr>
3038
+ </m:mc>
3039
+ </m:mcs>
3040
+ </m:mPr>
3041
+ <xsl:for-each select="*">
3042
+ <xsl:choose>
3043
+ <xsl:when test="self::mml:mtr or self::mml:mlabeledtr">
3044
+ <m:mr>
3045
+ <xsl:choose>
3046
+ <xsl:when test="self::mml:mtr">
3047
+ <xsl:for-each select="*">
3048
+ <m:e>
3049
+ <xsl:apply-templates select="." />
3050
+ </m:e>
3051
+ </xsl:for-each>
3052
+ <xsl:call-template name="CreateEmptyElmt">
3053
+ <xsl:with-param name="cEmptyMtd" select="$cMaxElmtsInRow - count(*)" />
3054
+ </xsl:call-template>
3055
+ </xsl:when>
3056
+ <xsl:otherwise>
3057
+ <xsl:for-each select="*[position() &gt; 1]">
3058
+ <m:e>
3059
+ <xsl:apply-templates select="." />
3060
+ </m:e>
3061
+ </xsl:for-each>
3062
+ <xsl:call-template name="CreateEmptyElmt">
3063
+ <xsl:with-param name="cEmptyMtd" select="$cMaxElmtsInRow - (count(*) - 1)" />
3064
+ </xsl:call-template>
3065
+ </xsl:otherwise>
3066
+ </xsl:choose>
3067
+ </m:mr>
3068
+ </xsl:when>
3069
+ <xsl:otherwise>
3070
+ <m:mr>
3071
+ <m:e>
3072
+ <xsl:apply-templates select="." />
3073
+ </m:e>
3074
+ <xsl:call-template name="CreateEmptyElmt">
3075
+ <xsl:with-param name="cEmptyMtd" select="$cMaxElmtsInRow - 1" />
3076
+ </xsl:call-template>
3077
+ </m:mr>
3078
+ </xsl:otherwise>
3079
+ </xsl:choose>
3080
+ </xsl:for-each>
3081
+ </m:m>
3082
+ </xsl:otherwise>
3083
+ </xsl:choose>
3084
+ </xsl:template>
3085
+ <xsl:template match="m:mtd">
3086
+ <xsl:apply-templates select="*" />
3087
+ </xsl:template>
3088
+ <xsl:template name="CreateEmptyElmt">
3089
+ <xsl:param name="cEmptyMtd" />
3090
+ <xsl:if test="$cEmptyMtd &gt; 0">
3091
+ <m:e></m:e>
3092
+ <xsl:call-template name="CreateEmptyElmt">
3093
+ <xsl:with-param name="cEmptyMtd" select="$cEmptyMtd - 1" />
3094
+ </xsl:call-template>
3095
+ </xsl:if>
3096
+ </xsl:template>
3097
+ <xsl:template name="CountMaxElmtsInRow">
3098
+ <xsl:param name="ndCur" />
3099
+ <xsl:param name="cMaxElmtsInRow" select="0" />
3100
+ <xsl:choose>
3101
+ <xsl:when test="not($ndCur)">
3102
+ <xsl:value-of select="$cMaxElmtsInRow" />
3103
+ </xsl:when>
3104
+ <xsl:otherwise>
3105
+ <xsl:call-template name="CountMaxElmtsInRow">
3106
+ <xsl:with-param name="ndCur" select="$ndCur/following-sibling::*[1]" />
3107
+ <xsl:with-param name="cMaxElmtsInRow">
3108
+ <xsl:choose>
3109
+ <xsl:when test="local-name($ndCur) = 'mlabeledtr' and
3110
+ namespace-uri($ndCur) = 'http://www.w3.org/1998/Math/MathML'">
3111
+ <xsl:choose>
3112
+ <xsl:when test="(count($ndCur/*) - 1) &gt; $cMaxElmtsInRow">
3113
+ <xsl:value-of select="count($ndCur/*) - 1" />
3114
+ </xsl:when>
3115
+ <xsl:otherwise>
3116
+ <xsl:value-of select="$cMaxElmtsInRow" />
3117
+ </xsl:otherwise>
3118
+ </xsl:choose>
3119
+ </xsl:when>
3120
+ <xsl:when test="local-name($ndCur) = 'mtr' and
3121
+ namespace-uri($ndCur) = 'http://www.w3.org/1998/Math/MathML'">
3122
+ <xsl:choose>
3123
+ <xsl:when test="count($ndCur/*) &gt; $cMaxElmtsInRow">
3124
+ <xsl:value-of select="count($ndCur/*)" />
3125
+ </xsl:when>
3126
+ <xsl:otherwise>
3127
+ <xsl:value-of select="$cMaxElmtsInRow" />
3128
+ </xsl:otherwise>
3129
+ </xsl:choose>
3130
+ </xsl:when>
3131
+ <xsl:otherwise>
3132
+ <xsl:choose>
3133
+ <xsl:when test="1 &gt; $cMaxElmtsInRow">
3134
+ <xsl:value-of select="1" />
3135
+ </xsl:when>
3136
+ <xsl:otherwise>
3137
+ <xsl:value-of select="$cMaxElmtsInRow" />
3138
+ </xsl:otherwise>
3139
+ </xsl:choose>
3140
+ </xsl:otherwise>
3141
+ </xsl:choose>
3142
+ </xsl:with-param>
3143
+ </xsl:call-template>
3144
+ </xsl:otherwise>
3145
+ </xsl:choose>
3146
+ </xsl:template>
3147
+
3148
+ <xsl:template name="GetMglyphAltText">
3149
+ <xsl:param name="ndCur" select="." />
3150
+ <xsl:choose>
3151
+ <xsl:when test="$ndCur/@alt">
3152
+ <xsl:value-of select="normalize-space($ndCur/@alt)"/>
3153
+ </xsl:when>
3154
+ <xsl:otherwise>
3155
+ <xsl:value-of select="normalize-space($ndCur/@mml:alt)"/>
3156
+ </xsl:otherwise>
3157
+ </xsl:choose>
3158
+ </xsl:template>
3159
+
3160
+ <xsl:template match="mml:mglyph">
3161
+ <xsl:element name="m:r">
3162
+ <xsl:element name="m:rPr">
3163
+ <xsl:element name="m:nor" />
3164
+ </xsl:element>
3165
+ <xsl:element name="m:t">
3166
+ <xsl:call-template name="OutputText">
3167
+ <xsl:with-param name="sInput">
3168
+ <xsl:call-template name="GetMglyphAltText">
3169
+ <xsl:with-param name="ndCur" select="." />
3170
+ </xsl:call-template>
3171
+ </xsl:with-param>
3172
+ </xsl:call-template>
3173
+ </xsl:element>
3174
+ </xsl:element>
3175
+ </xsl:template>
3176
+
3177
+ <!-- Omml doesn't really support mglyph, so just output the alt text -->
3178
+ <xsl:template match="mml:mi[child::mml:mglyph] |
3179
+ mml:mn[child::mml:mglyph] |
3180
+ mml:mo[child::mml:mglyph] |
3181
+ mml:ms[child::mml:mglyph] |
3182
+ mml:mtext[child::mml:mglyph]">
3183
+ <xsl:variable name="mathvariant">
3184
+ <xsl:choose>
3185
+ <xsl:when test="@mathvariant">
3186
+ <xsl:value-of select="@mathvariant"/>
3187
+ </xsl:when>
3188
+ <xsl:otherwise>
3189
+ <xsl:value-of select="@mml:mathvariant"/>
3190
+ </xsl:otherwise>
3191
+ </xsl:choose>
3192
+ </xsl:variable>
3193
+ <xsl:variable name="fontstyle">
3194
+ <xsl:choose>
3195
+ <xsl:when test="@fontstyle">
3196
+ <xsl:value-of select="@fontstyle"/>
3197
+ </xsl:when>
3198
+ <xsl:otherwise>
3199
+ <xsl:value-of select="@mml:fontstyle"/>
3200
+ </xsl:otherwise>
3201
+ </xsl:choose>
3202
+ </xsl:variable>
3203
+ <xsl:variable name="fontweight">
3204
+ <xsl:choose>
3205
+ <xsl:when test="@fontweight">
3206
+ <xsl:value-of select="@fontweight"/>
3207
+ </xsl:when>
3208
+ <xsl:otherwise>
3209
+ <xsl:value-of select="@mml:fontweight"/>
3210
+ </xsl:otherwise>
3211
+ </xsl:choose>
3212
+ </xsl:variable>
3213
+ <xsl:variable name="mathcolor">
3214
+ <xsl:choose>
3215
+ <xsl:when test="@mathcolor">
3216
+ <xsl:value-of select="@mathcolor"/>
3217
+ </xsl:when>
3218
+ <xsl:otherwise>
3219
+ <xsl:value-of select="@mml:mathcolor"/>
3220
+ </xsl:otherwise>
3221
+ </xsl:choose>
3222
+ </xsl:variable>
3223
+ <xsl:variable name="mathsize">
3224
+ <xsl:choose>
3225
+ <xsl:when test="@mathsize">
3226
+ <xsl:value-of select="@mathsize"/>
3227
+ </xsl:when>
3228
+ <xsl:otherwise>
3229
+ <xsl:value-of select="@mml:mathsize"/>
3230
+ </xsl:otherwise>
3231
+ </xsl:choose>
3232
+ </xsl:variable>
3233
+ <xsl:variable name="color">
3234
+ <xsl:choose>
3235
+ <xsl:when test="@color">
3236
+ <xsl:value-of select="@color"/>
3237
+ </xsl:when>
3238
+ <xsl:otherwise>
3239
+ <xsl:value-of select="@mml:color"/>
3240
+ </xsl:otherwise>
3241
+ </xsl:choose>
3242
+ </xsl:variable>
3243
+ <xsl:variable name="fontsize">
3244
+ <xsl:choose>
3245
+ <xsl:when test="@fontsize">
3246
+ <xsl:value-of select="@fontsize"/>
3247
+ </xsl:when>
3248
+ <xsl:otherwise>
3249
+ <xsl:value-of select="@mml:fontsize"/>
3250
+ </xsl:otherwise>
3251
+ </xsl:choose>
3252
+ </xsl:variable>
3253
+ <xsl:variable name="fNor">
3254
+ <xsl:call-template name="FNor">
3255
+ <xsl:with-param name="ndCur" select="." />
3256
+ </xsl:call-template>
3257
+ </xsl:variable>
3258
+
3259
+ <!-- Output MS Left Quote (if need be) -->
3260
+ <xsl:if test="self::mml:ms">
3261
+ <xsl:variable name="chLquote">
3262
+ <xsl:call-template name="LQuoteFromMs">
3263
+ <xsl:with-param name="curMs" select="." />
3264
+ </xsl:call-template>
3265
+ </xsl:variable>
3266
+ <xsl:element name="m:r">
3267
+ <xsl:call-template name="CreateRunProp">
3268
+ <xsl:with-param name="mathvariant" select="$mathvariant" />
3269
+ <xsl:with-param name="fontstyle" select="$fontstyle" />
3270
+ <xsl:with-param name="fontweight" select="$fontweight" />
3271
+ <xsl:with-param name="mathcolor" select="$mathcolor" />
3272
+ <xsl:with-param name="mathsize" select="$mathsize" />
3273
+ <xsl:with-param name="color" select="$color" />
3274
+ <xsl:with-param name="fontsize" select="$fontsize" />
3275
+ <xsl:with-param name="fNor" select="$fNor" />
3276
+ <xsl:with-param name="ndCur" select="." />
3277
+ </xsl:call-template>
3278
+ <xsl:element name="m:t">
3279
+ <xsl:call-template name="OutputText">
3280
+ <xsl:with-param name="sInput" select="$chLquote"/>
3281
+ </xsl:call-template>
3282
+ </xsl:element>
3283
+ </xsl:element>
3284
+ </xsl:if>
3285
+ <xsl:for-each select="mml:mglyph | text()">
3286
+ <xsl:variable name="fForceNor">
3287
+ <xsl:choose>
3288
+ <xsl:when test="self::mml:mglyph">1</xsl:when>
3289
+ <xsl:otherwise>0</xsl:otherwise>
3290
+ </xsl:choose>
3291
+ </xsl:variable>
3292
+
3293
+ <xsl:variable name="str">
3294
+ <xsl:choose>
3295
+ <xsl:when test="self::mml:mglyph">
3296
+ <xsl:call-template name="GetMglyphAltText">
3297
+ <xsl:with-param name="ndCur" select="." />
3298
+ </xsl:call-template>
3299
+ </xsl:when>
3300
+ <xsl:otherwise>
3301
+ <xsl:value-of select="normalize-space(.)"/>
3302
+ </xsl:otherwise>
3303
+ </xsl:choose>
3304
+ </xsl:variable>
3305
+ <xsl:if test="string-length($str) &gt; 0">
3306
+ <xsl:element name="m:r">
3307
+ <xsl:call-template name="CreateRunProp">
3308
+ <xsl:with-param name="mathvariant" select="$mathvariant" />
3309
+ <xsl:with-param name="fontstyle" select="$fontstyle" />
3310
+ <xsl:with-param name="fontweight" select="$fontweight" />
3311
+ <xsl:with-param name="mathcolor" select="$mathcolor" />
3312
+ <xsl:with-param name="mathsize" select="$mathsize" />
3313
+ <xsl:with-param name="color" select="$color" />
3314
+ <xsl:with-param name="fontsize" select="$fontsize" />
3315
+ <xsl:with-param name="fNor">
3316
+ <xsl:choose>
3317
+ <xsl:when test="$fForceNor=1">1</xsl:when>
3318
+ <xsl:otherwise>
3319
+ <xsl:value-of select="$fNor"/>
3320
+ </xsl:otherwise>
3321
+ </xsl:choose>
3322
+ </xsl:with-param>
3323
+ <xsl:with-param name="ndCur" select="." />
3324
+ </xsl:call-template>
3325
+ <xsl:element name="m:t">
3326
+ <xsl:call-template name="OutputText">
3327
+ <xsl:with-param name="sInput" select="$str"/>
3328
+ </xsl:call-template>
3329
+ </xsl:element>
3330
+ </xsl:element>
3331
+ </xsl:if>
3332
+ </xsl:for-each>
3333
+
3334
+ <!-- Output MS Right Quote (if need be) -->
3335
+ <xsl:if test="self::mml:ms">
3336
+ <xsl:variable name="chRquote">
3337
+ <xsl:call-template name="RQuoteFromMs">
3338
+ <xsl:with-param name="curMs" select="." />
3339
+ </xsl:call-template>
3340
+ </xsl:variable>
3341
+ <xsl:element name="m:r">
3342
+ <xsl:call-template name="CreateRunProp">
3343
+ <xsl:with-param name="mathvariant" select="$mathvariant" />
3344
+ <xsl:with-param name="fontstyle" select="$fontstyle" />
3345
+ <xsl:with-param name="fontweight" select="$fontweight" />
3346
+ <xsl:with-param name="mathcolor" select="$mathcolor" />
3347
+ <xsl:with-param name="mathsize" select="$mathsize" />
3348
+ <xsl:with-param name="color" select="$color" />
3349
+ <xsl:with-param name="fontsize" select="$fontsize" />
3350
+ <xsl:with-param name="fNor" select="$fNor" />
3351
+ <xsl:with-param name="ndCur" select="." />
3352
+ </xsl:call-template>
3353
+ <xsl:element name="m:t">
3354
+ <xsl:call-template name="OutputText">
3355
+ <xsl:with-param name="sInput" select="$chRquote"/>
3356
+ </xsl:call-template>
3357
+ </xsl:element>
3358
+ </xsl:element>
3359
+ </xsl:if>
3360
+ </xsl:template>
3361
+
3362
+ <xsl:template name="FStrContainsNonZeroDigit">
3363
+ <xsl:param name="s" />
3364
+
3365
+ <!-- Translate any nonzero digit into a 9 -->
3366
+ <xsl:variable name="sNonZeroDigitsToNineDigit" select="translate($s, '12345678', '99999999')" />
3367
+ <xsl:choose>
3368
+ <!-- Search for 9s -->
3369
+ <xsl:when test="contains($sNonZeroDigitsToNineDigit, '9')">1</xsl:when>
3370
+ <xsl:otherwise>0</xsl:otherwise>
3371
+ </xsl:choose>
3372
+ </xsl:template>
3373
+
3374
+ <xsl:template name="FStrContainsDigits">
3375
+ <xsl:param name="s" />
3376
+
3377
+ <!-- Translate any digit into a 0 -->
3378
+ <xsl:variable name="sDigitsToZeroDigit" select="translate($s, '123456789', '000000000')" />
3379
+ <xsl:choose>
3380
+ <!-- Search for 0s -->
3381
+ <xsl:when test="contains($sDigitsToZeroDigit, '0')">1</xsl:when>
3382
+ <xsl:otherwise>0</xsl:otherwise>
3383
+ </xsl:choose>
3384
+ </xsl:template>
3385
+
3386
+
3387
+ <!-- Used to determine if mpadded attribute {width, height, depth }
3388
+ indicates to show everything.
3389
+
3390
+ Unlike mathml, whose mpadded structure has great flexibility in modifying the
3391
+ bounding box's width, height, and depth, Word can only have zero or full width, height, and depth.
3392
+ Thus, if the width, height, or depth attributes indicate any kind of nonzero width, height,
3393
+ or depth, we'll translate that into a show full width, height, or depth for OMML. Only if the attribute
3394
+ indicates a zero width, height, or depth, will we report back FFull as false.
3395
+
3396
+ Example: s=0% -> FFull returns 0.
3397
+ s=2% -> FFull returns 1.
3398
+ s=0.1em -> FFull returns 1.
3399
+
3400
+ -->
3401
+ <xsl:template name="FFull">
3402
+ <xsl:param name="s" />
3403
+
3404
+ <xsl:variable name="fStrContainsNonZeroDigit">
3405
+ <xsl:call-template name="FStrContainsNonZeroDigit">
3406
+ <xsl:with-param name="s" select="$s" />
3407
+ </xsl:call-template>
3408
+ </xsl:variable>
3409
+
3410
+ <xsl:variable name="fStrContainsDigits">
3411
+ <xsl:call-template name="FStrContainsDigits">
3412
+ <xsl:with-param name="s" select="$s" />
3413
+ </xsl:call-template>
3414
+ </xsl:variable>
3415
+
3416
+ <xsl:choose>
3417
+ <!-- String contained non-zero digit -->
3418
+ <xsl:when test="$fStrContainsNonZeroDigit=1">1</xsl:when>
3419
+ <!-- String didn't contain a non-zero digit, but it did contain digits.
3420
+ This must mean that all digits in the string were 0s. -->
3421
+ <xsl:when test="$fStrContainsDigits=1">0</xsl:when>
3422
+ <!-- Else, no digits, therefore, return true.
3423
+ We return true in the otherwise condition to take account for the possibility
3424
+ in MathML to say something like width="height". -->
3425
+ <xsl:otherwise>1</xsl:otherwise>
3426
+ </xsl:choose>
3427
+ </xsl:template>
3428
+
3429
+
3430
+ <!-- Just outputs phant properties, doesn't do any fancy
3431
+ thinking of its own, just obeys the defaults of
3432
+ phants. -->
3433
+ <xsl:template name="CreatePhantPropertiesCore">
3434
+ <xsl:param name="fShow" select="1" />
3435
+ <xsl:param name="fFullWidth" select="1" />
3436
+ <xsl:param name="fFullHeight" select="1" />
3437
+ <xsl:param name="fFullDepth" select="1" />
3438
+
3439
+ <xsl:if test="$fShow=0
3440
+ or $fFullWidth=0
3441
+ or $fFullHeight=0
3442
+ or $fFullDepth=0">
3443
+ <xsl:element name="m:phantPr">
3444
+ <xsl:if test="$fShow=0">
3445
+ <xsl:element name="m:show">
3446
+ <xsl:attribute name="m:val">off</xsl:attribute>
3447
+ </xsl:element>
3448
+ </xsl:if>
3449
+ <xsl:if test="$fFullWidth=0">
3450
+ <xsl:element name="m:zeroWid">
3451
+ <xsl:attribute name="m:val">on</xsl:attribute>
3452
+ </xsl:element>
3453
+ </xsl:if>
3454
+ <xsl:if test="$fFullHeight=0">
3455
+ <xsl:element name="m:zeroAsc">
3456
+ <xsl:attribute name="m:val">on</xsl:attribute>
3457
+ </xsl:element>
3458
+ </xsl:if>
3459
+ <xsl:if test="$fFullDepth=0">
3460
+ <xsl:element name="m:zeroDesc">
3461
+ <xsl:attribute name="m:val">on</xsl:attribute>
3462
+ </xsl:element>
3463
+ </xsl:if>
3464
+ </xsl:element>
3465
+ </xsl:if>
3466
+ </xsl:template>
3467
+
3468
+ <!-- Figures out if we should factor in width, height, and depth attributes.
3469
+
3470
+ If so, then it
3471
+ gets these attributes, does some processing to figure out what the attributes indicate,
3472
+ then passes these indications to CreatePhantPropertiesCore.
3473
+
3474
+ If we aren't supposed to factor in width, height, or depth, then we'll just output the show
3475
+ attribute. -->
3476
+ <xsl:template name="CreatePhantProperties">
3477
+ <xsl:param name="ndCur" select="." />
3478
+ <xsl:param name="fShow" select="1"/>
3479
+
3480
+ <xsl:choose>
3481
+ <!-- In the special case that we have an mphantom with one child which is an mpadded, then we should
3482
+ subsume the mpadded attributes into the mphantom attributes. The test statement below imples the
3483
+ 'one child which is an mpadded'. The first part, that the parent of mpadded is an mphantom, is implied
3484
+ by being in this template, which is only called when we've encountered an mphantom.
3485
+
3486
+ Word outputs its invisible phantoms with smashing as
3487
+
3488
+ <mml:mphantom>
3489
+ <mml:mpadded . . . >
3490
+
3491
+ </mml:mpadded>
3492
+ </mml:mphantom>
3493
+
3494
+ This test is used to allow roundtripping smashed invisible phantoms. -->
3495
+ <xsl:when test="count($ndCur/child::*)=1 and count($ndCur/mml:mpadded)=1">
3496
+ <xsl:variable name="sLowerCaseWidth">
3497
+ <xsl:choose>
3498
+ <xsl:when test="$ndCur/mml:mpadded/@width">
3499
+ <xsl:value-of select="translate($ndCur/mml:mpadded/@width, $StrUCAlphabet, $StrLCAlphabet)"/>
3500
+ </xsl:when>
3501
+ <xsl:otherwise>
3502
+ <xsl:value-of select="translate($ndCur/mml:mpadded/@mml:width, $StrUCAlphabet, $StrLCAlphabet)"/>
3503
+ </xsl:otherwise>
3504
+ </xsl:choose>
3505
+ </xsl:variable>
3506
+ <xsl:variable name="sLowerCaseHeight">
3507
+ <xsl:choose>
3508
+ <xsl:when test="$ndCur/mml:mpadded/@height">
3509
+ <xsl:value-of select="translate($ndCur/mml:mpadded/@height, $StrUCAlphabet, $StrLCAlphabet)"/>
3510
+ </xsl:when>
3511
+ <xsl:otherwise>
3512
+ <xsl:value-of select="translate($ndCur/mml:mpadded/@mml:height, $StrUCAlphabet, $StrLCAlphabet)"/>
3513
+ </xsl:otherwise>
3514
+ </xsl:choose>
3515
+ </xsl:variable>
3516
+ <xsl:variable name="sLowerCaseDepth">
3517
+ <xsl:choose>
3518
+ <xsl:when test="$ndCur/mml:mpadded/@depth">
3519
+ <xsl:value-of select="translate($ndCur/mml:mpadded/@depth, $StrUCAlphabet, $StrLCAlphabet)"/>
3520
+ </xsl:when>
3521
+ <xsl:otherwise>
3522
+ <xsl:value-of select="translate($ndCur/mml:mpadded/@mml:depth, $StrUCAlphabet, $StrLCAlphabet)"/>
3523
+ </xsl:otherwise>
3524
+ </xsl:choose>
3525
+ </xsl:variable>
3526
+
3527
+ <xsl:variable name="fFullWidth">
3528
+ <xsl:call-template name="FFull">
3529
+ <xsl:with-param name="s" select="$sLowerCaseWidth" />
3530
+ </xsl:call-template>
3531
+ </xsl:variable>
3532
+ <xsl:variable name="fFullHeight">
3533
+ <xsl:call-template name="FFull">
3534
+ <xsl:with-param name="s" select="$sLowerCaseHeight" />
3535
+ </xsl:call-template>
3536
+ </xsl:variable>
3537
+ <xsl:variable name="fFullDepth">
3538
+ <xsl:call-template name="FFull">
3539
+ <xsl:with-param name="s" select="$sLowerCaseDepth" />
3540
+ </xsl:call-template>
3541
+ </xsl:variable>
3542
+
3543
+ <xsl:call-template name="CreatePhantPropertiesCore">
3544
+ <xsl:with-param name="fShow" select="$fShow"/>
3545
+ <xsl:with-param name="fFullWidth" select="$fFullWidth" />
3546
+ <xsl:with-param name="fFullHeight" select="$fFullHeight" />
3547
+ <xsl:with-param name="fFullDepth" select="$fFullDepth" />
3548
+ </xsl:call-template>
3549
+ </xsl:when>
3550
+ <xsl:otherwise>
3551
+ <xsl:call-template name="CreatePhantPropertiesCore">
3552
+ <xsl:with-param name="fShow" select="$fShow"/>
3553
+ </xsl:call-template>
3554
+ </xsl:otherwise>
3555
+ </xsl:choose>
3556
+ </xsl:template>
3557
+
3558
+ <xsl:template match="mml:mpadded">
3559
+ <xsl:choose>
3560
+ <xsl:when test="count(parent::mml:mphantom)=1 and count(preceding-sibling::*)=0 and count(following-sibling::*)=0">
3561
+ <!-- This mpadded is inside an mphantom that has already setup phantom attributes, therefore, just apply templates -->
3562
+ <xsl:apply-templates select="*" />
3563
+ </xsl:when>
3564
+ <xsl:otherwise>
3565
+ <xsl:variable name="sLowerCaseWidth">
3566
+ <xsl:choose>
3567
+ <xsl:when test="@width">
3568
+ <xsl:value-of select="@width"/>
3569
+ </xsl:when>
3570
+ <xsl:otherwise>
3571
+ <xsl:value-of select="@mml:width"/>
3572
+ </xsl:otherwise>
3573
+ </xsl:choose>
3574
+ </xsl:variable>
3575
+ <xsl:variable name="sLowerCaseHeight">
3576
+ <xsl:choose>
3577
+ <xsl:when test="@height">
3578
+ <xsl:value-of select="@height"/>
3579
+ </xsl:when>
3580
+ <xsl:otherwise>
3581
+ <xsl:value-of select="@mml:height"/>
3582
+ </xsl:otherwise>
3583
+ </xsl:choose>
3584
+ </xsl:variable>
3585
+ <xsl:variable name="sLowerCaseDepth">
3586
+ <xsl:choose>
3587
+ <xsl:when test="@depth">
3588
+ <xsl:value-of select="@depth"/>
3589
+ </xsl:when>
3590
+ <xsl:otherwise>
3591
+ <xsl:value-of select="@mml:depth"/>
3592
+ </xsl:otherwise>
3593
+ </xsl:choose>
3594
+ </xsl:variable>
3595
+
3596
+ <xsl:variable name="fFullWidth">
3597
+ <xsl:call-template name="FFull">
3598
+ <xsl:with-param name="s" select="$sLowerCaseWidth" />
3599
+ </xsl:call-template>
3600
+ </xsl:variable>
3601
+ <xsl:variable name="fFullHeight">
3602
+ <xsl:call-template name="FFull">
3603
+ <xsl:with-param name="s" select="$sLowerCaseHeight" />
3604
+ </xsl:call-template>
3605
+ </xsl:variable>
3606
+ <xsl:variable name="fFullDepth">
3607
+ <xsl:call-template name="FFull">
3608
+ <xsl:with-param name="s" select="$sLowerCaseDepth" />
3609
+ </xsl:call-template>
3610
+ </xsl:variable>
3611
+
3612
+ <xsl:element name="m:phant">
3613
+ <xsl:call-template name="CreatePhantPropertiesCore">
3614
+ <xsl:with-param name="fShow" select="1"/>
3615
+ <xsl:with-param name="fFullWidth" select="$fFullWidth" />
3616
+ <xsl:with-param name="fFullHeight" select="$fFullHeight" />
3617
+ <xsl:with-param name="fFullDepth" select="$fFullDepth" />
3618
+ </xsl:call-template>
3619
+ <m:e>
3620
+ <xsl:apply-templates select="*" />
3621
+ </m:e>
3622
+ </xsl:element>
3623
+ </xsl:otherwise>
3624
+ </xsl:choose>
3625
+ </xsl:template>
3626
+
3627
+ <xsl:template match="mml:mphantom">
3628
+ <xsl:element name="m:phant">
3629
+ <xsl:call-template name="CreatePhantProperties">
3630
+ <xsl:with-param name="ndCur" select="." />
3631
+ <xsl:with-param name="fShow" select="0" />
3632
+ </xsl:call-template>
3633
+ <m:e>
3634
+ <xsl:apply-templates select="*" />
3635
+ </m:e>
3636
+ </xsl:element>
3637
+ </xsl:template>
3638
+
3639
+ <xsl:template name="isNaryOper">
3640
+ <xsl:param name="sNdCur" />
3641
+ <xsl:value-of select="($sNdCur = '&#x222B;'
3642
+ or $sNdCur = '&#x222C;'
3643
+ or $sNdCur = '&#x222D;'
3644
+ or $sNdCur = '&#x222E;'
3645
+ or $sNdCur = '&#x222F;'
3646
+ or $sNdCur = '&#x2230;'
3647
+ or $sNdCur = '&#x2232;'
3648
+ or $sNdCur = '&#x2233;'
3649
+ or $sNdCur = '&#x2231;'
3650
+ or $sNdCur = '&#x2229;'
3651
+ or $sNdCur = '&#x222A;'
3652
+ or $sNdCur = '&#x220F;'
3653
+ or $sNdCur = '&#x2210;'
3654
+ or $sNdCur = '&#x2211;'
3655
+ or $sNdCur = '&#x22C0;'
3656
+ or $sNdCur = '&#x22C1;'
3657
+ or $sNdCur = '&#x22C2;'
3658
+ or $sNdCur = '&#x22C3;')" />
3659
+ </xsl:template>
3660
+
3661
+
3662
+ <xsl:template name="isNary">
3663
+ <!-- ndCur is the element around the nAry operator -->
3664
+ <xsl:param name="ndCur" />
3665
+ <xsl:variable name="sNdCur">
3666
+ <xsl:value-of select="normalize-space($ndCur)" />
3667
+ </xsl:variable>
3668
+
3669
+ <xsl:variable name="fNaryOper">
3670
+ <xsl:call-template name="isNaryOper">
3671
+ <xsl:with-param name="sNdCur" select="$sNdCur" />
3672
+ </xsl:call-template>
3673
+ </xsl:variable>
3674
+
3675
+ <!-- Narys shouldn't be MathML accents. -->
3676
+ <xsl:variable name="fUnder">
3677
+ <xsl:choose>
3678
+ <xsl:when test="$ndCur/parent::*[self::mml:munder]">1</xsl:when>
3679
+ <xsl:otherwise>0</xsl:otherwise>
3680
+ </xsl:choose>
3681
+ </xsl:variable>
3682
+
3683
+ <xsl:variable name="sLowerCaseAccent">
3684
+ <xsl:choose>
3685
+ <xsl:when test="$fUnder=1">
3686
+ <xsl:choose>
3687
+ <xsl:when test="$ndCur/parent::*[self::mml:munder]/@accentunder">
3688
+ <xsl:value-of select="translate($ndCur/parent::*[self::mml:munder]/@accentunder, $StrUCAlphabet, $StrLCAlphabet)"/>
3689
+ </xsl:when>
3690
+ <xsl:otherwise>
3691
+ <xsl:value-of select="translate($ndCur/parent::*[self::mml:munder]/@mml:accentunder, $StrUCAlphabet, $StrLCAlphabet)"/>
3692
+ </xsl:otherwise>
3693
+ </xsl:choose>
3694
+ </xsl:when>
3695
+ <xsl:otherwise>
3696
+ <xsl:choose>
3697
+ <xsl:when test="$ndCur/parent::*/@accent">
3698
+ <xsl:value-of select="translate($ndCur/parent::*/@accent, $StrUCAlphabet, $StrLCAlphabet)"/>
3699
+ </xsl:when>
3700
+ <xsl:otherwise>
3701
+ <xsl:value-of select="translate($ndCur/parent::*/@mml:accent, $StrUCAlphabet, $StrLCAlphabet)"/>
3702
+ </xsl:otherwise>
3703
+ </xsl:choose>
3704
+ </xsl:otherwise>
3705
+ </xsl:choose>
3706
+ </xsl:variable>
3707
+
3708
+ <xsl:variable name="fAccent">
3709
+ <xsl:choose>
3710
+ <xsl:when test="$sLowerCaseAccent='true'">1</xsl:when>
3711
+ <xsl:otherwise>0</xsl:otherwise>
3712
+ </xsl:choose>
3713
+ </xsl:variable>
3714
+
3715
+ <xsl:choose>
3716
+ <!-- This ndCur is in fact part of an nAry if
3717
+
3718
+ 1) The last descendant of ndCur (which could be ndCur itself) is an operator.
3719
+ 2) Along that chain of descendants we only encounter mml:mo, mml:mstyle, and mml:mrow elements.
3720
+ 3) the operator in mml:mo is a valid nAry operator
3721
+ 4) The nAry is not accented.
3722
+ -->
3723
+ <xsl:when test="$fNaryOper = 'true'
3724
+ and $fAccent=0
3725
+ and $ndCur/descendant-or-self::*[last()]/self::mml:mo
3726
+ and not($ndCur/descendant-or-self::*[not(self::mml:mo or
3727
+ self::mml:mstyle or
3728
+ self::mml:mrow)])">
3729
+ <xsl:value-of select="true()" />
3730
+ </xsl:when>
3731
+ <xsl:otherwise>
3732
+ <xsl:value-of select="false()" />
3733
+ </xsl:otherwise>
3734
+ </xsl:choose>
3735
+ </xsl:template>
3736
+
3737
+ <xsl:template name="CreateNaryProp">
3738
+ <xsl:param name="chr" />
3739
+ <xsl:param name="sMathmlType" />
3740
+ <xsl:param name="sGrow">
3741
+ <xsl:choose>
3742
+ <xsl:when test="child::*[1]/@stretchy">
3743
+ <xsl:value-of select="translate(child::*[1]/@stretchy, $StrUCAlphabet, $StrLCAlphabet)"/>
3744
+ </xsl:when>
3745
+ <xsl:otherwise>
3746
+ <xsl:value-of select="translate(child::*[1]/@mml:stretchy, $StrUCAlphabet, $StrLCAlphabet)"/>
3747
+ </xsl:otherwise>
3748
+ </xsl:choose>
3749
+ </xsl:param>
3750
+ <m:naryPr>
3751
+ <m:chr>
3752
+ <xsl:attribute name="m:val">
3753
+ <xsl:value-of select="$chr" />
3754
+ </xsl:attribute>
3755
+ </m:chr>
3756
+ <m:limLoc>
3757
+ <xsl:attribute name="m:val">
3758
+ <xsl:choose>
3759
+ <xsl:when test="$sMathmlType='munder' or
3760
+ $sMathmlType='mover' or
3761
+ $sMathmlType='munderover'">
3762
+ <xsl:text>undOvr</xsl:text>
3763
+ </xsl:when>
3764
+ <xsl:when test="$sMathmlType='msub' or
3765
+ $sMathmlType='msup' or
3766
+ $sMathmlType='msubsup'">
3767
+ <xsl:text>subSup</xsl:text>
3768
+ </xsl:when>
3769
+ </xsl:choose>
3770
+ </xsl:attribute>
3771
+ </m:limLoc>
3772
+ <m:grow>
3773
+ <xsl:attribute name="m:val">
3774
+ <xsl:choose>
3775
+ <xsl:when test="$sGrow='true'">1</xsl:when>
3776
+ <xsl:when test="$sGrow='false'">0</xsl:when>
3777
+ <xsl:when test="$chr='&#x222B;'
3778
+ or $chr='&#x222E;'
3779
+ or $chr='&#x222F;'
3780
+ or $chr='&#x2232;'
3781
+ or $chr='&#x2233;'
3782
+ or $chr='&#x2229;'
3783
+ or $chr='&#x222A;'
3784
+ or $chr='&#x220F;'
3785
+ or $chr='&#x2211;'
3786
+ or $chr='&#x22C0;'
3787
+ or $chr='&#x22C1;'
3788
+ or $chr='&#x22C2;'
3789
+ or $chr='&#x22C3;'">1</xsl:when>
3790
+ <xsl:otherwise>0</xsl:otherwise>
3791
+ </xsl:choose>
3792
+ </xsl:attribute>
3793
+ </m:grow>
3794
+ <m:subHide>
3795
+ <xsl:attribute name="m:val">
3796
+ <xsl:choose>
3797
+ <xsl:when test="$sMathmlType='mover' or
3798
+ $sMathmlType='msup'">
3799
+ <xsl:text>on</xsl:text>
3800
+ </xsl:when>
3801
+ <xsl:otherwise>
3802
+ <xsl:text>off</xsl:text>
3803
+ </xsl:otherwise>
3804
+ </xsl:choose>
3805
+ </xsl:attribute>
3806
+ </m:subHide>
3807
+ <m:supHide>
3808
+ <xsl:attribute name="m:val">
3809
+ <xsl:choose>
3810
+ <xsl:when test="$sMathmlType='munder' or
3811
+ $sMathmlType='msub'">
3812
+ <xsl:text>on</xsl:text>
3813
+ </xsl:when>
3814
+ <xsl:otherwise>
3815
+ <xsl:text>off</xsl:text>
3816
+ </xsl:otherwise>
3817
+ </xsl:choose>
3818
+ </xsl:attribute>
3819
+ </m:supHide>
3820
+ </m:naryPr>
3821
+ </xsl:template>
3822
+ </xsl:stylesheet>