Lua 中的 MathML 格式 XML

Lua 中的 MathML 格式 XML

我已经成功加载了 XML LuaLaTeX。但是如何加载MathML。任何Lua 模块有空吗?

我的 LaTeX 文件:

\documentclass{article}
\usepackage{luacode}
\begin{luacode*}
xml = require('luaxml-mod-xml')
handler = require('luaxml-mod-handler')
\end{luacode*}
\begin{document}
\begin{luacode*}
sample = [[
<?xml version="1.0" encoding="utf-8"?>
<art>
<title>Scattering of flexural waves an electric current</title>
<para>Smart testing structures are components <math display="inline" overflow="scroll"><mrow><mi>G</mi><mo>&#x3d;</mo><mrow><mo stretchy="false">(</mo><mi>V</mi><mo>,</mo><mi>E</mi><mo stretchy="false">)</mo></mrow></mrow></math> used in engineering applications that are capable of sensing or reacting to their environment in a predictable and desired manner. In addition to carrying mechanical loads, smart structures may alleviate vibration, reduce acoustic noise, change their mechanical properties as required or monitor their own condition.</para>
</art>
]]
XMLIn = handler.simpleTreeHandler()
x = xml.xmlParser(XMLIn)
x:parse(sample)
tex.sprint(XMLIn.root["art"]["title"])
tex.sprint(XMLIn.root["art"]["para"])
\end{luacode*}
\end{document}

答案1

LuaXML库提供了更多高级库来处理 XML,luaxml-domobject它可以在 JavaScript 中创建类似于 HTML DOM 的 DOM 结构。

我创建了一个简单的库,可以处理您提供的 XML。它不支持完整的 MathML,但添加对其他元素的支持并不难。以下是完整代码process_xml.lua

kpse.set_program_name "luatex"
local domobject = require "luaxml-domobject"

-- we need to define different actions for XML elements. The default action is
-- to just process child elements and return the result
local function default_action(element)
  return process_children(element)
end

-- use template string to place the processed children
local function simple_content(s)
  return function(element)
    local content = process_children(element)
    return string.format(s, content)
  end
end

local function math_action(element)
  local content = process_children(element)
  local display = element:get_attribute("display") or "inline"
  local template = "$%s$" 
  if display == "block" then template = "\n\\[\n%s\n\\]\n" end
  return string.format(template, content)
end

local mathvariant_templates = {
  normal = "\\mathrm{%s}",
  identifier = "\\operatorname{%s}" -- this needs amsmath package
  -- there are lot more, see https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mi
}

local function mi_action(element)
  local content = process_children(element)
  -- how should be <mi> rendered is based on the length.
  -- one character should be rendered in italic, two and more characters
  -- act like identifier like \sin
  local implicit_mathvariant = utf8.len(content) > 1 and "identifier" or "italic"
  -- the rendering can be also based on the mathvariant attribute
  local mathvariant = element:get_attribute("mathvariant") or implicit_mathvariant
  local template = mathvariant_templates[mathvariant] or "%s"
  return string.format(template, content)

end

local function get_child_element(element, count)
  -- return specified child element 
  local i = 0
  for _, el in ipairs(element:get_children()) do
    -- count elements 
    if el:is_element() then
      -- return the desired numbered element
      i = i + 1
      if i == count then return el end
    end
  end
end

local function frac_action(element)
  -- <mfrac> should have two children, we need to process them separatelly
  local numerator = process_children(get_child_element(element, 1))
  local denominator = process_children(get_child_element(element, 2))
  return string.format("\\frac{%s}{%s}", numerator, denominator)
end

-- actions for particular elements
local actions = {
  title = simple_content("\\section{%s}\n"),
  para = simple_content("%s\n\\par"),
  math = math_action,
  mi = mi_action,
  mfrac = frac_action, -- example of element that needs to process the children separatelly
  -- here you can add more elements, like <mo> etc.
}

-- convert Unicode characters to TeX sequences
local unicodes = {
   [960] = "\\pi{}"
}

local function process_text(text)
  local t = {}
  -- process all Unicode characters and find if they should be replaced
  for _, char in utf8.codes(text) do
    -- construct new string with replacements or original char
    t[#t+1] = unicodes[char] or utf8.char(char)
  end
  return table.concat(t)
end

function process_children(element)
  -- accumulate text from children elements
  local t = {}
  -- sometimes we may get text node
  if type(element) ~= "table" then return element end
  for i, elem in ipairs(element:get_children()) do
    if elem:is_text() then
      -- concat text
      t[#t+1] = process_text(elem:get_text())
    elseif elem:is_element() then
      -- recursivelly process child elements
      t[#t+1] = process_tree(elem)
    end
  end
  return table.concat(t)
end


function process_tree(element)
  -- find specific action for the element, or use the default action
  local element_name = element:get_element_name()
  local action = actions[element_name] or default_action
  return action(element)
end

function parse_xml(content)
  -- parse XML string and process it
  local dom = domobject.parse(content)
  -- start processing of DOM from the root element
  -- return string with TeX content
  return process_tree(dom:root_node())
end


function print_tex(content)
  -- we need to replace "\n" characters with calls to tex.sprint
  for s in content:gmatch("([^\n]*)") do
    tex.sprint(s)
  end
end

local M = {
  parse_xml = parse_xml,
  print_tex = print_tex
}

return M

它提供了两个主要函数,parse_xml,将 XML 字符串转换为 TeX 字符串,以及print_tex,将 TeX 字符串打印到文档中。您不能tex.sprint直接使用,因为换行符无法正确处理。

您可以配置三个表:

mathvariant_templates- 该表提供以下配置<mi>元素mathvariant属性。它应该包含函数模板string.format。这是默认的:

local mathvariant_templates = {
  normal = "\\mathrm{%s}",
  identifier = "\\operatorname{%s}" -- this needs amsmath package
  -- there are lot more, see https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mi
}

unicodes- 应使用 LaTeX 宏替换的字符的 Unicode 代码点。LuaXML 将使用 Unicode 替换 XML 实体,因此您应该在此处放置 \pi 等内容。这是默认设置:

-- convert Unicode characters to TeX sequences
local unicodes = {
   [960] = "\\pi{}"
}

最重要的配置是actions。这将处理元素。默认情况下,元素的所有内容都会被处理,因此您只需配置要采取特殊操作的元素。

我添加了一些辅助函数:

simple_content采用string.format模板并%s用元素子的内容替换字符。

更高级的功能如math_actionmi_action可以通过分析内容或元素属性来决定做什么。

有些元素有固定数量的子元素,例如<mfrac>,它应该有两个子元素。我们希望将其转换为\frac宏,它需要两个参数。在这种情况下,我们需要分别处理这两个子元素。函数frac_action处理这个问题。对于我未实现的其他一些 MathML 元素,您将需要类似的函数。

这是的默认内容actions

-- actions for particular elements
local actions = {
  title = simple_content("\\section{%s}\n"),
  para = simple_content("%s\n\\par"),
  math = math_action,
  mi = mi_action,
  mfrac = frac_action, -- example of element that needs to process the children separatelly
  -- here you can add more elements, like <mo> etc.
}

以下是 TeX 文件示例:

\documentclass{article}
\usepackage{amsmath}
\usepackage{luacode}
\begin{document}
\begin{luacode*}
local process_xml = require "process_xml"    
sample = [[
<?xml version="1.0" encoding="utf-8"?>
<art>
<title>Scattering of flexural waves an electric current</title>
<para>Smart testing structures are components <math display="inline" overflow="scroll"><mrow><mi>G</mi><mo>&#x3d;</mo><mrow><mo stretchy="false">(</mo><mi>V</mi><mo>,</mo><mi>E</mi><mo stretchy="false">)</mo></mrow></mrow></math> used in engineering applications that are capable of sensing or reacting to their environment in a predictable and desired manner. In addition to carrying mechanical loads, smart structures may alleviate vibration, reduce acoustic noise, change their mechanical properties as required or monitor their own condition.</para>
<para>
More examples: <math>
  <mi>sin</mi><mi>x</mi>
</math> or Pi: <math><mi>&pi;</mi></math>
</para>
<math display="block">
<mfrac><mi>a</mi><mi>b</mi></mfrac>
</math>
</art>
]]
process_xml.print_tex(process_xml.parse_xml(sample))
\end{luacode*}
\end{document}

它的渲染方式如下:

在此处输入图片描述

相关内容