我参考了我的问题和解决方案\ifthenelse 中的字符串比较我希望我能把我的问题说清楚,我不是技术人员。
我使用一种数据库文件(简单文本文件),其中包含翻译的根节,我可以从中检索到不同出版物中的单个节。在上面链接的问题中,有两种解决方案可以解析数据库并检索节。一种(A)基于 LaTeX2,另一种(B)基于 LaTeX3(xparse)。两者都在一定程度上完成了工作,并且两者都有不同的限制,我将尝试解释。也许您可以帮助修复其中一种以满足我的需求。
请查看 MWE。在我的“数据库”中,每个条目由一行文本组成。当找到某个键时,命令“mystanza”会格式化并打印值(节)以及两个§§之间的字符,请查看输出。
我遇到的问题是,在解决方案 A 中,数据库文本不能包含任何 LaTeX 命令。这意味着我无法格式化文本(例如,强调或在其中放置段落命令)。
(一)LaTeX2
\documentclass[a4paper,12pt]{article}
\usepackage{filecontents}
\begin{filecontents*}{stanzas.dat}
+1§1§||{This is stanza one from chapter one.}
+2§2§||{This is stanza two from chapter two.}
+3§3§||{This is stanza three from chapter three.}
+4§4§||{This is stanza four from chapter four. But there is problem with \emph{formatting} text.}
\end{filecontents*}
\usepackage{fontspec}
\defaultfontfeatures{Mapping=tex-text} %
\usepackage{polyglossia}
\setdefaultlanguage[spelling=new, babelshorthands=true]{german}
\usepackage{xstring}
\usepackage{xifthen}
\usepackage{stringstrings}
\newcommand*{\isinxp}[2]{\expandafter\isinxpp\expandafter{#2}{#1}}
\newcommand*{\isinxpp}[2]{\isin {#2}{#1}}
\newread\dbroot
\newcommand{\mystanza}[1]{%
\openin\dbroot=stanzas.dat
{\loop
\endlinechar=-1
\read\dbroot to \dbline
\unless\ifeof\dbroot
\ifthenelse{\isinxp{#1}{\dbline}}
{\StrCut{\dbline}{||}{\colA}{\colB}%
(\StrBetween[1,2]{\colA}{§}{§})~{\colB}}%
{}%
\repeat}%
\closein\dbroot
}
\begin{document}
\mystanza{+1§1§}
\mystanza{+2§2§}
\mystanza{+3§3§}
% \mystanza{+4§4§} % <-- problematic
\end{document}
(二)LaTeX3(xparser)
解决方案 B 针对我的数据库文件密钥的另一种格式编写:§2§~{text}
现在是+1§2§||{}
。使用更改后的密钥,它会产生错误(一个是由于我在密钥中更改为~
)||
。不过,它对数据库文本中的 LaTeX 代码没有任何问题。
\documentclass[a4paper,12pt]{article}
\usepackage{filecontents}
\begin{filecontents*}{morestanzas.dat}
§1§~{This is stanza one from \emph{chapter} one.}
§2§||{This is stanza two from chapter two.}
+3§3§||{This is stanza three from \emph{chapter} three.}
\end{filecontents*}
\usepackage{xparse}
\ExplSyntaxOn
% generic command
\NewDocumentCommand{\printdata}{ mm }
{% #1 is the file name, #2 is the key to test
\christof_printdata:nn { #1 } { #2 }
}
% with fixed file name
\NewDocumentCommand{\mystanza}{ m }
{
\printdata{morestanzas.dat} { #1 } % <--- file name
}
\ior_new:N \g_christof_data_stream
\seq_new:N \l__christof_entry_seq
\cs_new_protected:Npn \christof_printdata:nn #1 #2
{
\ior_open:Nn \g_christof_data_stream { #1 }
\ior_map_inline:Nn \g_christof_data_stream
{
\tl_if_in:nnT { ##1 } { #2 }
{
\__christof_process_line:ww ##1 \q_stop
}
}
}
\group_begin:
\char_set_catcode_active:N \^^A
\char_set_lccode:nn { `\^^A } { `\~ }
\tl_to_lowercase:n
{
\group_end:
\cs_new_protected:Npn \__christof_process_line:ww §#1§ ^^A #2 \q_stop
}
{% #1 is the key, #2 is the value
(#1) \nobreakspace \tl_trim_spaces:n { #2 }
}
\ExplSyntaxOff
\begin{document}
\mystanza{§1§}
% \mystanza{§2§} <--- problem 1
% \mystanza{§3§} <--- problem 2
\end{document}
答案1
这采用了不同的方法,使用readarray
包。但是,它确实要求您的文件在节标识符和括号括起来的节之间stanzas.dat
使用空格分隔符,而不是分隔符。||
\documentclass[a4paper,12pt]{article}
\usepackage[T1]{fontenc}
\usepackage{readarray,ifthen}
\usepackage{filecontents}
\begin{filecontents*}{stanzas.dat}
+1§1§ {This is stanza one from chapter one.}
+2§2§ {This is stanza two from chapter two.}
+3§3§ {This is stanza three from chapter three.}
+4§4§ {This is stanza four from chapter four. And there is no longer a problem with \emph{formatting} text.}
\end{filecontents*}
\readdef{stanzas.dat}{\stanzas}
\readArrayij{\stanzas}{stz}{2}
\newcounter{sindex}
\newcommand\mystanza[1]{%
\setcounter{sindex}{0}%
\whiledo{\thesindex < \stzROWS\relax}{%
\stepcounter{sindex}%
\ifthenelse{\equal{\arrayij{stz}{\thesindex}{1}}{#1}}%
{\arrayij{stz}{\thesindex}{2}}{}%
}%
}
%\usepackage{fontspec}
%\defaultfontfeatures{Mapping=tex-text} %
%\usepackage{polyglossia}
%\setdefaultlanguage[spelling=new, babelshorthands=true]{german}
\begin{document}
This shows how the data is stored:
Element(3,1): \arrayij{stz}{3}{1}
Element(3,2): \arrayij{stz}{3}{2}
Number of rows: \stzROWS
Here is what you want
\mystanza{+1§1§}
\mystanza{+3§3§}
\mystanza{+4§4§}
\mystanza{+2§2§}
\end{document}