我在 Debian squeeze 上使用 Tex Live 2009。如果真的需要,我可以升级,但我宁愿不升级。我想知道是否可以执行以下操作。
给定(关系)数据库中的一些数据,我可以提取它并自动将其格式化为 LaTeX 表,这样如果数据发生变化,就不需要手动重新创建 LaTeX 表了?可以用 Lua 做这样的事情吗?通常,人们会为此使用合适的语言数据库适配器,而我看到 Lua 有LuaSQL。我想使用 PostgreSQL。我目前使用的是 8.4 版。
不涉及 Lua 的解决方案也很好。需要说明的是,我对 Lua 一无所知,而且我对 LaTeX 编程的了解也非常有限。我正在寻找一种可以在必要时进行调整的方法。虽然这对我当前的用例来说并不重要,但如果可能的话,它似乎是一种有用的通用技术。
答案1
假设您想要这个输出:
如果您使用 LuaTeX,最具创新性的方法就是在您的程序中包含 luasql 绑定。
首先创建一个简单的数据库(createdb.txt
):
CREATE TABLE people(
name varchar(50),
email varchar(50)
);
INSERT INTO "people" VALUES('Jose das Couves','[email protected]');
INSERT INTO "people" VALUES('Manoel Joaquim','[email protected]');
INSERT INTO "people" VALUES('Maria das Dores','[email protected]');
并填充sqlite3 luasql-test < createdb.txt
下一步是创建一个简单的 LuaLaTeX 文档并将文件读入表中:
\documentclass{article}
\usepackage{luacode,booktabs}
\begin{document}
\begin{luacode*}
require("luasql.sqlite3")
env = assert (luasql.sqlite3())
-- connect to data source
con = assert (env:connect("luasql-test"))
-- retrieve a cursor
cur = assert (con:execute"SELECT name, email from people")
-- print all rows, the rows will be indexed by field names
row = cur:fetch ({}, "a")
tex.sprint([[\begin{tabular}{@{}ll@{}}\toprule]])
tex.sprint([[Name & email \\\midrule]])
while row do
tex.sprint(-2,row.name)
tex.sprint("&")
tex.sprint(-2, row.email)
tex.sprint("\\\\")
-- reusing the table of results
row = cur:fetch (row, "a")
end
tex.sprint([[\bottomrule\end{tabular}]])
-- close everything
cur:close()
con:close()
env:close()
\end{luacode*}
\end{document}
(该示例取自luasql主页。
我跳过了最糟糕的部分:编译和安装。这高度依赖于系统,但我会列出一些步骤/陷阱。
- 在 MacOS X 上,您无法
sqlite3.so
直接使用来自 luasql 的,因为luatex
二进制文件缺少一些符号。因此,您需要编译自己的未剥离的 luatex 二进制文件 (./build.sh --nostrip
) 并使用它。它需要放在 tex 树中的“原始”版本中。如果您已经这样做了,您可以使用sqlite3.so
来自 luasql 项目。在其他 unix 系统上可能也是如此。请参阅错误跟踪器中的条目 666。 - 在您的文档目录中创建一个名为的目录
luasql
,并将生成的库放在那里。 - 您需要 LuaTeX 版本 > 0.46.0。因此 texlive 2011 可能是最佳选择。
- 我下载了luasql的源码发行版,自己编译了一下,不知道基于luarocks的安装能不能用(应该是可以的)。
答案2
以下代码源自聊天室中的讨论。这里的想法是将数据检索和处理留给外部实体,设置一个.tex
模板来保存数据,填充数据并生成最终.tex
文件。
.tex
这就是模板引擎的基本功能。虽然我们可以利用 Lua(参见 Patrick 的精彩回答),但有时为了简单起见,您可能只依赖模板。:)
开始吧,代码被分成几部分,以包含对每个部分发生的事情的一些注释。我选择用 Python 编写一个小脚本,并完全依赖硬编码数据和模板来简化流程。
from xml.dom import minidom
from Cheetah.Template import Template
我决定坚持使用一些以 XML 格式表示的数据,因为这只是获取数据并将其合并到 TeX 的一个简单示例。当然,我们获取内容的方式现在无关紧要,因为我们只对数据对象在脚本中的表示方式感兴趣。:)
我曾经minidom
读过 XML 摘录和猎豹模板引擎帮助我生成结果.tex
文件。目前,这些只是导入,我们将在下一步中讨论实现。
def getNodeValue(node, key):
return node.getElementsByTagName(key)[0].childNodes[0].nodeValue
def getData(source):
a = []
b = minidom.parseString(source)
c = b.firstChild
for d in c.childNodes:
if d.nodeType == 1:
e = {}
e['name'] = getNodeValue(d, 'name')
e['surname'] = getNodeValue(d, 'surname')
e['grade'] = float(getNodeValue(d, 'grade'))
a.append(e)
return a
这两个函数只是为了帮助我遍历 XML 内容并获取我想要的数据而编写的。结果将是一个包含以下形式的字典的数组
{
'name' : 'John',
'surname' : 'Doe',
'grade' : 10
}
从以下 XML 中提取,以原始字符串的形式用 Python 代码表示(请注意r
字符串定义中的前缀):
xml = r"""<?xml version="1.0" ?>
<persons>
<person>
<name>Paulo</name>
<surname>Cereda</surname>
<grade>3.6</grade>
</person>
<person>
<name>Enrico</name>
<surname>Gregorio</surname>
<grade>8.9</grade>
</person>
<person>
<name>David</name>
<surname>Carlisle</surname>
<grade>8.8</grade>
</person>
</persons>"""
现在,让我们开始最有趣的部分。一切准备就绪后,让我们读取 XML 内容,解析它并创建数组。我通过调用getData
之前定义的函数来执行此操作。为了更有趣,我将一个sorted
函数应用于结果数组,提供一个 lambda 函数,该函数按键设置顺序name
:
data = sorted(getData(xml), key=lambda y: y['name'])
该data
变量包含一个字典数组。现在让我们创建.tex
模板,与创建 XML 文件的方式基本相同,即通过原始字符串:
template = r"""\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{siunitx}
\begin{document}
\begin{tabular}{llS}
\hline
Name & Surname & {Grade}\\
\hline
#for $person in $data
$person['name'] & $person['surname'] & $person['grade']\\
#end for
\hline
\end{tabular}
\end{document}"""
模板非常简单,它是一个简单的.tex
文件,它将为我们提供一个tabular
环境。有趣的部分是:
#for $person in $data
$person['name'] & $person['surname'] & $person['grade']\\
#end for
这部分是猎豹语言描述。简而言之,这是一个for
循环,我们迭代data
数组中的所有字典。请注意,$
用作占位符,而不是数学模式,就像我们在 TeX 中使用的一样。不用担心它们,一旦我们合并所有内容,它们就会消失。:)
由于我们处理的是字典,我们从它的键访问值,因此$person['name']
将返回该人的名字。:)
现在,让我们从上面的源代码创建模板并添加data
与键关联的数组,然后打印模板。我应该将合并输出到一个新文件,但现在,我们只需将生成的代码打印到终端:
definition = Template(source=template, searchList=[ { 'data': data } ])
print(definition)
我们就完成了。:)
我把代码完整地贴出来,方便大家复制粘贴:
from xml.dom import minidom
from Cheetah.Template import Template
def getNodeValue(node, key):
return node.getElementsByTagName(key)[0].childNodes[0].nodeValue
def getData(source):
a = []
b = minidom.parseString(source)
c = b.firstChild
for d in c.childNodes:
if d.nodeType == 1:
e = {}
e['name'] = getNodeValue(d, 'name')
e['surname'] = getNodeValue(d, 'surname')
e['grade'] = float(getNodeValue(d, 'grade'))
a.append(e)
return a
xml = r"""<?xml version="1.0" ?>
<persons>
<person>
<name>Paulo</name>
<surname>Cereda</surname>
<grade>3.6</grade>
</person>
<person>
<name>Enrico</name>
<surname>Gregorio</surname>
<grade>8.9</grade>
</person>
<person>
<name>David</name>
<surname>Carlisle</surname>
<grade>8.8</grade>
</person>
</persons>"""
data = sorted(getData(xml), key=lambda y: y['name'])
template = r"""\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{siunitx}
\begin{document}
\begin{tabular}{llS}
\hline
Name & Surname & {Grade}\\
\hline
#for $person in $data
$person['name'] & $person['surname'] & $person['grade']\\
#end for
\hline
\end{tabular}
\end{document}"""
definition = Template(source=template, searchList=[ { 'data': data } ])
print(definition)
为了运行此代码,我们需要一个 Python 解释器(我的是Python 2.7.5
)和 Cheetah 模板引擎。我几乎确信您可以通过您最喜欢的包管理器安装它,例如
# yum install python-cheetah
或者可能通过pip
:
pip install Cheetah
现在让我们运行代码,好吗?:)
Allons-y!
paulo@alexandria ~$ python mycode.py
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{siunitx}
\begin{document}
\begin{tabular}{llS}
\hline
Name & Surname & {Grade}\\
\hline
David & Carlisle & 8.8\\
Enrico & Gregorio & 8.9\\
Paulo & Cereda & 3.6\\
\hline
\end{tabular}
\end{document}
生成的.tex
文件产生以下输出:
就是这样。:)
答案3
TeX dbi
河谷科技发布一款名为TeX dbi。我从来没有用过,但根据描述主页,软件
使 TeX 能够与兼容 SQL 的数据库引擎对话并生成漂亮的报告。
我甚至找到了文章描述TeX dbi
,参见拖船,第23卷(2002年)。该程序可从萨罗瓦 (TeX dbi)。Sarovar 上的文件似乎相当旧,因此我建议联系作者以验证这是否是最后一个版本。
SQLTeX
在CTAN 目录你会发现一款名为SQLTeX。我也没用过,但是根据readme文件中的介绍:
SQLTeX 是一个预处理器,用于在 LaTeX 中使用 SQL 语句。它是一个 perl 脚本,可读取包含 SQL 命令的输入文件,并编写可使用 LaTeX 包处理的 LaTeX 文件。
答案4
如果你能够从数据库创建 CSV,那么我建议使用数据工具包裹