Datatool 查询数据库 \dtlgetrowindex 参数扩展

Datatool 查询数据库 \dtlgetrowindex 参数扩展

我正在构建一个数据库,以便从文档的各个位置收集信息。我想执行以下操作:查询数据库以查找具有特定键值的行。如果找到这样的行(根据数据库的构造,该行应该是唯一的),则对该行执行某些操作,否则添加具有该键和值的新行。请注意,该值存储在宏中,并且事先不知道。问题是:实现此目的的最佳方法是什么?

我将描述我“不太成功”的尝试。本来应该是常规的数据库操作,结果却比我预期的要复杂得多(或者也许我不够开明)。

在第 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(但我不确定什么时候有机会这样做,因为我有一堆其他需要先做的事情)。

相关内容