将关系数据库中的数据读入 LaTeX 表

将关系数据库中的数据读入 LaTeX 表

我在 Debian squeeze 上使用 Tex Live 2009。如果真的需要,我可以升级,但我宁愿不升级。我想知道是否可以执行以下操作。

给定(关系)数据库中的一些数据,我可以提取它并自动将其格式化为 LaTeX 表,这样如果数据发生变化,就不需要手动重新创建 LaTeX 表了?可以用 Lua 做这样的事情吗?通常,人们会为此使用合适的语言数据库适配器,而我看到 Lua 有LuaSQL。我想使用 PostgreSQL。我目前使用的是 8.4 版。

不涉及 Lua 的解决方案也很好。需要说明的是,我对 Lua 一无所知,而且我对 LaTeX 编程的了解也非常有限。我正在寻找一种可以在必要时进行调整的方法。虽然这对我当前的用例来说并不重要,但如果可能的话,它似乎是一种有用的通用技术。

答案1

假设您想要这个输出:

来自 SQL 数据库的表

如果您使用 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,那么我建议使用数据工具包裹

相关内容