将表格拆分到下一页 - LuaLaTeX

将表格拆分到下一页 - LuaLaTeX

我需要在不使用longtable包的情况下将表格拆分到下一页。因为longtable包不直接支持float

我的 MWE 是:

\documentclass{article}
\usepackage{luacode}


\begin{document}

\begin{luacode*}
local domobject = require "luaxml-domobject"
sample = [[
<?xml version="1.0" encoding="utf-8"?>
<art>
<title>Scattering of flexural waves an electric current</title>
<p>From these observations, another important result is that the individual masses of such observed black hole&#x2013;black hole (BBHs) binaries can be much larger than what were expected previously both theoretically and observationally [14], and various scenarios have been proposed [<xref ref-type="bibr" rid="cqgab7bbabib2">2</xref>, <xref ref-type="bibr" rid="cqgab7bbabib26">26</xref>]. In particular, observations of the same signal in two different detectors provides an efficient independent way to cross check and validate the instruments, which is particularly valuable for a space-based detector behavior of these parameters is presented in the table <xref ref-type="table" rid="cqgab7bbat1">1</xref>.</p>
<table-wrap id="tab1" position="float" tab-row-break="5"><label>Table 1.</label><caption id="tab1"><p>The large <italic>x</italic> behavior for different <italic>w</italic>, where <italic>F</italic> means finite.</p></caption><table><colgroup><col align="left"/><col align="center"/><col align="center"/><col align="center"/><col align="center"/><col align="center"/><col align="center"/></colgroup><thead><tr><th>Parameters:</th><th>e<sup>2<italic>&#x3b3;</italic></sup></th><th><italic>r</italic><sup>2</sup></th><th><italic>&#x3c1;</italic></th><th><italic>L</italic></th><th><italic>V</italic></th><th><italic>E</italic></th></tr></thead><tbody><tr><td>A1</td><td>&#x221e;</td><td>&#x221e;</td><td>0</td><td>&#x221e;</td><td>&#x221e;</td><td><italic>F</italic></td></tr><tr><td>B2</td><td>0</td><td>&#x221e;</td><td><italic>F</italic></td><td><italic>F</italic></td><td><italic>F</italic></td></tr><tr><td>C3</td><td>&#x221e;</td><td>0</td><td><italic>F</italic></td><td><italic>F</italic></td><td><italic>F</italic></td></tr><tr><td>D4</td><td>0</td><td>&#x221e;</td><td><italic>F</italic></td><td><italic>F</italic></td><td><italic>F</italic></td><td><italic>F</italic></td></tr><tr><td>E5</td><td>0</td><td>&#x221e;</td><td>&#x221e;</td><td><italic>F</italic></td><td><italic>F</italic></td><td><italic>F</italic></td></tr><tr><td>F6</td><td>&#x221e;</td><td>&#x221e;</td><td>0</td><td>&#x221e;</td><td>&#x221e;</td><td><italic>F</italic></td></tr><tr><td>G7</td><td>&#x221e;</td><td>&#x221e;</td><td>0</td><td>&#x221e;</td><td>&#x221e;</td><td><italic>F</italic></td></tr><tr><td>H8</td><td>&#x221e;</td><td>&#x221e;</td><td>0</td><td>&#x221e;</td><td>&#x221e;</td><td><italic>F</italic></td></tr><tr><td>I9</td><td>&#x221e;</td><td>&#x221e;</td><td>0</td><td>&#x221e;</td><td>&#x221e;</td><td><italic>F</italic></td></tr><tr><td>J10</td><td>&#x221e;</td><td>&#x221e;</td><td>0</td><td>&#x221e;</td><td>&#x221e;</td><td><italic>F</italic></td></tr></tbody></table></table-wrap>

</art>
]]

local dom = domobject.parse(sample)
\end{luacode*}
\end{document}

如果table属性是具有tab-row-break='5',我需要从而tbody不是在中计算表行thead,并且需要给出关闭tabular和打开新的tabular\end{tabular}\pagebreak\begin{tabular}{...}

如何实现这一点?

答案1

您可以使用库来转换 XML luaxml-transform,但是由于需要根据属性将表拆分为两个浮点数,因此这项任务变得更加困难tab-row-break。我们可以使用该luaxml-domobject库来预处理 XML,拆分表,然后我们可以轻松使用转换库。

这是完整的代码,我将在下面进行描述:

\documentclass{article}
\usepackage{fontspec}
\setmainfont{Linux Libertine O}
\usepackage{luacode}

% this is a modified version of \@makecaption from LaTeX classes
% it doesn't print : between table number and caption
\makeatletter
\newcommand\tablecaption[2]{%
  \vskip\abovecaptionskip
  \sbox\@tempboxa{\textbf{#1} #2}%
  \ifdim \wd\@tempboxa >\hsize
    \textbf{#1} #2\par
  \else
    \global \@minipagefalse
    \hb@xt@\hsize{\hfil\box\@tempboxa\hfil}%
  \fi
  \vskip\belowcaptionskip
}
\makeatother

\begin{document}

\begin{luacode*}
local domobject = require "luaxml-domobject"
local transform = require "luaxml-transform"
sample = [[
<?xml version="1.0" encoding="utf-8"?>
<art>
<title>Scattering of flexural waves an electric current</title>
<p>From these observations, another important result is that the individual masses of such observed black hole&#x2013;black hole (BBHs) binaries can be much larger than what were expected previously both theoretically and observationally [14], and various scenarios have been proposed [<xref ref-type="bibr" rid="cqgab7bbabib2">2</xref>, <xref ref-type="bibr" rid="cqgab7bbabib26">26</xref>]. In particular, observations of the same signal in two different detectors provides an efficient independent way to cross check and validate the instruments, which is particularly valuable for a space-based detector behavior of these parameters is presented in the table <xref ref-type="table" rid="cqgab7bbat1">1</xref>.</p>
<table-wrap id="tab1" position="float" tab-row-break="5"><label>Table 1.</label><caption id="tab1"><p>The large <italic>x</italic> behavior for different <italic>w</italic>, where <italic>F</italic> means finite.</p></caption><table><colgroup><col align="left"/><col align="center"/><col align="center"/><col align="center"/><col align="center"/><col align="center"/><col align="center"/></colgroup><thead><tr><th>Parameters:</th><th>e<sup>2<italic>&#x3b3;</italic></sup></th><th><italic>r</italic><sup>2</sup></th><th><italic>&#x3c1;</italic></th><th><italic>L</italic></th><th><italic>V</italic></th><th><italic>E</italic></th></tr></thead><tbody><tr><td>A1</td><td>&#x221e;</td><td>&#x221e;</td><td>0</td><td>&#x221e;</td><td>&#x221e;</td><td><italic>F</italic></td></tr><tr><td>B2</td><td>0</td><td>&#x221e;</td><td><italic>F</italic></td><td><italic>F</italic></td><td><italic>F</italic></td></tr><tr><td>C3</td><td>&#x221e;</td><td>0</td><td><italic>F</italic></td><td><italic>F</italic></td><td><italic>F</italic></td></tr><tr><td>D4</td><td>0</td><td>&#x221e;</td><td><italic>F</italic></td><td><italic>F</italic></td><td><italic>F</italic></td><td><italic>F</italic></td></tr><tr><td>E5</td><td>0</td><td>&#x221e;</td><td>&#x221e;</td><td><italic>F</italic></td><td><italic>F</italic></td><td><italic>F</italic></td></tr><tr><td>F6</td><td>&#x221e;</td><td>&#x221e;</td><td>0</td><td>&#x221e;</td><td>&#x221e;</td><td><italic>F</italic></td></tr><tr><td>G7</td><td>&#x221e;</td><td>&#x221e;</td><td>0</td><td>&#x221e;</td><td>&#x221e;</td><td><italic>F</italic></td></tr><tr><td>H8</td><td>&#x221e;</td><td>&#x221e;</td><td>0</td><td>&#x221e;</td><td>&#x221e;</td><td><italic>F</italic></td></tr><tr><td>I9</td><td>&#x221e;</td><td>&#x221e;</td><td>0</td><td>&#x221e;</td><td>&#x221e;</td><td><italic>F</italic></td></tr><tr><td>J10</td><td>&#x221e;</td><td>&#x221e;</td><td>0</td><td>&#x221e;</td><td>&#x221e;</td><td><italic>F</italic></td></tr></tbody></table></table-wrap>

</art>
]]

local dom = domobject.parse(sample)

-- prepare tables
for _, wrap in ipairs(dom:query_selector("table-wrap[tab-row-break]")) do
  local row_break = wrap:get_attribute("tab-row-break")
  local tables = wrap:query_selector("table") or {}
  -- we assume that there is just one table as <table-wrap> children
  local tbl = tables[1] 
  if tbl then
    -- convert <col> elements to latex specification and save it as an attribute
    local align = {}
    local align_convert = {left = "l", right = "r", center = "c"}
    for _, col in ipairs(tbl:query_selector("col")) do 
      local al = col:get_attribute("align") or "left"
      align[#align+1] = align_convert[al]
    end
    tbl:set_attribute("align", table.concat(align, " "))
  end
  -- create floats
  -- first save children
  local children = wrap:get_children()
  -- it will contain floats
  wrap._children = {}
  -- this is needed to fix a bug in LuaXML
  local function fix_parents(el)
    for k,v in ipairs(el._children or {}) do
      if v:is_element() then
        v._parent = el
        fix_parents(v)
      end
    end
  end
  for i = 1, 2 do
    local float = wrap:create_element("float")
    wrap:add_child_node(float)
    -- add saved children
    for _, child in ipairs(children) do
      -- save copy of the original child
      float:add_child_node(child:copy_node())
    end
    fix_parents(float)
  end
  -- now split tables
  local tbl = wrap:query_selector("table") 
  -- there should be two tables now
  if #tbl == 2 then
    local tbody = tbl[1]:query_selector("tbody tr")
    -- remove spurious rows from the first table
    for i = row_break + 1, #tbody do
      tbody[i]:remove_node()
    end
    -- remove spurious lines from the second table
    local tbody = tbl[2]:query_selector("tbody tr")
    for i = 1, row_break do
      tbody[i]:remove_node()
    end
  end
  -- place (continued...) text to second caption
  local captions = wrap:query_selector("caption")
  local caption = captions[2]
  if caption then
    -- remove original text
    caption._children = {}
    local par = caption:create_element("p")
    local text = par:create_text_node("(continued...)")
    par:add_child_node(text)
    caption:add_child_node(par)
  end
end

transformer = transform.new()
transformer:add_action("title", "\\section{@<.>}")
transformer:add_action("p", "@<.>\n\n")
transformer:add_action("table-wrap float", "\\begin{table}\n@<.>\n\\end{table}\n")
-- you need to define this command in your TeX file
transformer:add_action("table-wrap label", "\\tablecaption{@<.>}")
-- this is a second argument to \tablecaption
transformer:add_action("table-wrap caption", "{@<.>}\n\n")
transformer:add_action("italic", "\\textit{@<.>}")
transformer:add_action("sub", "\\textsubscript{@<.>}")
transformer:add_action("sup", "\\textsuperscript{@<.>}")
transformer:add_action("table", "\\begin{tabular}{@{align}}\n@<.>\\end{tabular}\n")
transformer:add_action("tr", "@<.>\\\\\n")
transformer:add_action("th", "@<.> &")
transformer:add_action("th:last-of-type", "@<.>")
transformer:add_action("tbody td", "@<.> &")
transformer:add_action("tbody td:last-of-type", "@<.>")

local content = transformer:process_dom(dom)
-- print(content)
-- print the transformed XML to LaTeX
transform.print_tex(content)
-- print(dom:serialize())
 
\end{luacode*}
\end{document}

这是处理表格的部分:

local dom = domobject.parse(sample)

-- prepare tables
for _, wrap in ipairs(dom:query_selector("table-wrap[tab-row-break]")) do
  local row_break = wrap:get_attribute("tab-row-break")
  local tables = wrap:query_selector("table") or {}
  -- we assume that there is just one table as <table-wrap> children
  local tbl = tables[1] 
  if tbl then
    -- convert <col> elements to latex specification and save it as an attribute
    local align = {}
    local align_convert = {left = "l", right = "r", center = "c"}
    for _, col in ipairs(tbl:query_selector("col")) do 
      local al = col:get_attribute("align") or "left"
      align[#align+1] = align_convert[al]
    end
    tbl:set_attribute("align", table.concat(align, " "))
  end
  -- create floats
  -- first save children
  local children = wrap:get_children()
  -- it will contain floats
  wrap._children = {}
  -- this is needed to fix a bug in LuaXML
  local function fix_parents(el)
    for k,v in ipairs(el._children or {}) do
      if v:is_element() then
        v._parent = el
        fix_parents(v)
      end
    end
  end
  for i = 1, 2 do
    local float = wrap:create_element("float")
    wrap:add_child_node(float)
    -- add saved children
    for _, child in ipairs(children) do
      -- save copy of the original child
      float:add_child_node(child:copy_node())
    end
    fix_parents(float)
  end
  -- now split tables
  local tbl = wrap:query_selector("table") 
  -- there should be two tables now
  if #tbl == 2 then
    local tbody = tbl[1]:query_selector("tbody tr")
    -- remove spurious rows from the first table
    for i = row_break + 1, #tbody do
      tbody[i]:remove_node()
    end
    -- remove spurious lines from the second table
    local tbody = tbl[2]:query_selector("tbody tr")
    for i = 1, row_break do
      tbody[i]:remove_node()
    end
  end
  -- place (continued...) text to second caption
  local captions = wrap:query_selector("caption")
  local caption = captions[2]
  if caption then
    -- remove original text
    caption._children = {}
    local par = caption:create_element("p")
    local text = par:create_text_node("(continued...)")
    par:add_child_node(text)
    caption:add_child_node(par)
  end
end

首先,它将列对齐信息转换为 LaTeX 表格规范,并将其保存为元素的属性<table>。它使转换更容易。然后,它创建两个浮动元素,并将原始表格内容复制到它们。然后,我们从两个副本中删除虚假的表格行,并将其设置(continued...)为第二个浮动元素的表格标题。

然后可以使用以下规则转换此 DOM 对象:

transformer = transform.new()
transformer:add_action("title", "\\section{@<.>}")
transformer:add_action("p", "@<.>\n\n")
transformer:add_action("table-wrap float", "\\begin{table}\n@<.>\n\\end{table}\n")
-- you need to define this command in your TeX file
transformer:add_action("table-wrap label", "\\tablecaption{@<.>}")
-- this is a second argument to \tablecaption
transformer:add_action("table-wrap caption", "{@<.>}\n\n")
transformer:add_action("italic", "\\textit{@<.>}")
transformer:add_action("sub", "\\textsubscript{@<.>}")
transformer:add_action("sup", "\\textsuperscript{@<.>}")
transformer:add_action("table", "\\begin{tabular}{@{align}}\n@<.>\\end{tabular}\n")
transformer:add_action("tr", "@<.>\\\\\n")
transformer:add_action("th", "@<.> &")
transformer:add_action("th:last-of-type", "@<.>")
transformer:add_action("tbody td", "@<.> &")
transformer:add_action("tbody td:last-of-type", "@<.>")

没什么特别的,只看到我们需要处理行中的最后一个项,以防止插入多余的&字符,这会导致编译错误。 这是我们所需要的规则tbody td:last-of-type

还要注意,我们使用align之前由 DOM 处理函数定义的属性来设置正确的表格声明。

我们还期望<label><caption>元素彼此相邻,因为它们产生命令\tablecaption,并且如果它们不在预期的位置,它就会中断。

最后,请注意您需要使用支持所有特殊字符的字体,例如我示例中的 Linux Libertine。

结果如下:

在此处输入图片描述

相关内容