我正在构建一个数据库,以便从文档的各个位置收集信息。我想执行以下操作:查询数据库以查找具有特定键值的行。如果找到这样的行(根据数据库的构造,该行应该是唯一的),则对该行执行某些操作,否则添加具有该键和值的新行。请注意,该值存储在宏中,并且事先不知道。问题是:实现此目的的最佳方法是什么?
我将描述我“不太成功”的尝试。本来应该是常规的数据库操作,结果却比我预期的要复杂得多(或者也许我不够开明)。
在第 96 页上对示例进行 Minicing数据工具用户手册,我有以下(不)工作的代码。我理解原因是\dtlgetrowindex
没有扩展其参数\foo
(稍后会详细介绍)。
\documentclass{article}
\usepackage{datatool}
\begin{document}
\DTLnewdb{mydb}
\DTLnewrow{mydb}
\DTLnewdbentry{mydb}{Animals}{cat}
\DTLnewrow{mydb}
\DTLnewdbentry{mydb}{Animals}{dog}
\DTLnewrow{mydb}
\DTLnewdbentry{mydb}{Animals}{pig}
\DTLnewrow{mydb}
\DTLnewdbentry{mydb}{Animals}{sheep}
\def \foo{dog}
\dtlgetrowindex{\myrowidx}{mydb}{1}{\foo}
\ifx\myrowidx\dtlnovalue
Not Found
\else
Found in row \myrowidx
\fi
\end{document}
输出将是
未找到
正如我之前提到的,传递给 时参数\foo
不会被扩展\dtlgetrow
,从而导致匹配未找到。我非常努力地解决这个问题,最后一次“成功”的尝试是基于Werner 对另一个数据工具问题的回答
\makeatletter
\begingroup
\let \dtlgetrowindex\relax%
\protected@xdef\GetRowIndex#1{
\dtlgetrowindex{#1}{mydb}{1}{\foo}
}
\endgroup
\makeatother
\GetRowIndex{\myrowidx}
\ifx\myrowidx\dtlnovalue
Not Found
\else
Found in row \myrowidx
\fi
这将产生
在第 2 行找到
但这肯定不是预期用途吧?
我还尝试遍历数据库并找到匹配项。再次获得部分“成功”:
\def\foo{humming bird}
\newcounter{mycnt}
\begin{DTLenvforeach}[\DTLiseq{\foo}{\animals}]{mydb}{\animals=Animals}
%Found match!
\DTLappendtorow{Class}{Bird}
\stepcounter{mycnt}
\end{DTLenvforeach}
\ifnum \themycnt=0
\DTLnewrow{mydb}
\DTLnewdbentry{mydb}{Animals}{hummingbird}
\DTLnewdbentry{mydb}{Class}{Bird}
\fi
\DTLdisplaydb{mydb}
我认为这是一种相当违反直觉的做法:(1) 检查整个数据库,(2) 必须引入一个额外的变量来跟踪迭代。此外,我称其为部分成功,因为显然,\DTLiseq
它从参数中删除了所有空格,如以下代码所示:
\ifthenelse{\DTLiseq{football}{ f o o t b a l l }}{Equal!}{Not equal!}
产生(为什么?)
平等的!
我认为两个单词连接在一起可能会变成第三个单词,但它们的含义不同。删除所有空格可消除差异。
答案1
\dtlgetrowindex
定义如下:
\newcommand*{\dtlgetrowindex}[4]{%
\toks@{#4}%
\edef\dtl@dogetrowindex{\noexpand\@dtlgetrowindex{\noexpand#1}{#2}{\number#3}{\the\toks@}}%
\dtl@dogetrowindex
}
该值暂时存储在令牌寄存器中,以防止扩展。我们可以定义一个允许扩展的修改版本:
\newcommand*{\xdtlgetrowindex}[4]{%
\protected@edef\dtl@dogetrowindex{\noexpand\@dtlgetrowindex{\noexpand#1}{#2}{\number#3}{#4}}%
\dtl@dogetrowindex
}
在文档中定义时,需要将其括在\makeatletter
/中:\makeatother
\documentclass{article}
\usepackage{datatool}
\makeatletter
\providecommand*{\xdtlgetrowindex}[4]{%
\protected@edef\dtl@dogetrowindex{\noexpand\@dtlgetrowindex{\noexpand#1}{#2}{\number#3}{#4}}%
\dtl@dogetrowindex
}
\makeatother
\begin{document}
\DTLnewdb{mydb}
\DTLnewrow{mydb}
\DTLnewdbentry{mydb}{Animals}{cat}
\DTLnewrow{mydb}
\DTLnewdbentry{mydb}{Animals}{dog}
\DTLnewrow{mydb}
\DTLnewdbentry{mydb}{Animals}{pig}
\DTLnewrow{mydb}
\DTLnewdbentry{mydb}{Animals}{sheep}
\def\foo{dog}
\xdtlgetrowindex{\myrowidx}{mydb}{1}{\foo}
\ifx\myrowidx\dtlnovalue
Not Found
\else
Found in row \myrowidx
\fi
\end{document}
这正确产生:
在第 2 行找到
我已经用过了\providecommand
,我会把它添加到下一个版本中datatool
(但我不确定什么时候有机会这样做,因为我有一堆其他需要先做的事情)。