diff options
Diffstat (limited to 'tex/context/base/xtag-map.mkii')
-rw-r--r-- | tex/context/base/xtag-map.mkii | 746 |
1 files changed, 746 insertions, 0 deletions
diff --git a/tex/context/base/xtag-map.mkii b/tex/context/base/xtag-map.mkii new file mode 100644 index 000000000..cbde4f1b1 --- /dev/null +++ b/tex/context/base/xtag-map.mkii @@ -0,0 +1,746 @@ +%D \module +%D [ file=xtag-map, +%D version=2000.12.20, +%D title=\CONTEXT\ XML Macros, +%D subtitle=Remapping, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA / Hans Hagen \& Ton Otten}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D There is a more versatile mapper available in \type {xtag-rem.tex}! + +%D We also need something that lets content as-is, like for +%D instance XML embedded in a chemical caption. + +\writestatus{loading}{ConTeXt XML Macros / Remapping} + +%D A fundamental characteristic of \TEX\ is that much +%D processing depends on picking up one or more arguments and +%D acting upon them. In \type {xtag-ini} we have implemented +%D the normal (high) level interface between \XML\ and +%D \CONTEXT, and there we already saw some ways to pick up an +%D element as argument. +%D +%D In this module we will implement a preprocessor. An element +%D that feeds its content to the preprocessor, becomes a token +%D list consisting of \TEX\ macros, which in turn may expand to +%D their meanings. +%D +%D This module is only tested with \ETEX. In principle we can +%D make it work with good old \TEX, but we see no objection +%D against using \ETEX, especially since it's part of every +%D grown up \TEX\ distribution. + +\unprotect + +\let\normalparseXMLescape \parseXMLescape +\let\normalparseXMLelement\parseXMLelement +\let\normalparseXMLprocess\parseXMLprocess + +\let\normaldoXMLelement \doXMLelement +\let\normaldoXMLentity \doXMLentity + +\def\setnormalXMLhandler + {\let\doXMLelement \normaldoXMLelement + \let\parseXMLelement\normalparseXMLelement + \let\parseXMLescape \normalparseXMLescape + \let\parseXMLprocess\normalparseXMLprocess + \let\doXMLentity \normaldoXMLentity} + +%D A careful reader will notice that we do a full expansion of +%D the content of the element, although commands that are +%D protected will stay untouched. In this stage we also +%D collect key|/|value pairs and pass them onto the \TEX\ +%D macros if needed. Again, we need a fully expandable parser +%D to handle this, which make the core macros slightly +%D unreadable. +%D +%D The interface presented here evolved from an older module, +%D written on top of \type {m-sgml}, that could take care of +%D \MATHML\ (version 1). The implementation here is more +%D advanced in the sense that it permits all kind of parsers. + +\def\findendofXMLelement#1% space after 0/1 prevents auto \relax + {\if#1>0 \else + \if#1/1 \endofXMLelementE\else + \if#1"\endofXMLelementD \else + \if#1'\endofXMLelementS \else + \endofXMLelementN \fi\fi\fi\fi} + +\def\endofXMLelementE#1\fi\fi\fi\fi#2>{\fi\fi} +\def\endofXMLelementD#1\fi\fi\fi\fi#2"{\fi\fi\fi \findendofXMLelement} +\def\endofXMLelementS#1\fi\fi\fi\fi#2'{\fi\fi\fi\fi\findendofXMLelement} +\def\endofXMLelementN \fi\fi\fi\fi {\fi\fi\fi\fi\findendofXMLelement} + +% not faster +% +% \def\findendofXMLelement#1% +% {\csname**\if#1>>\else\if#1//\else\if#1""\else\if#1''\else.\fi\fi\fi\fi\endcsname} +% +% \def\findendofXMLelement#1% +% {\csname**\ifcsname**#1\endcsname#1\else.\fi\endcsname} +% +% \setvalue{**>}{0 } +% \setvalue{**/}#1>{1 } +% \setvalue{**"}#1"{\findendofXMLelement} +% \setvalue{**'}#1'{\findendofXMLelement} +% \letvalue{**.}\findendofXMLelement + +\newif\ifremapXMLunknown + +%D We need three steps to avoid namespace: tag since comment +%D and processing instructions don't have a namespace. The +%D first step distinguishes between comment, processing +%D instructions and elements. The second step (which is +%D defined in the main mapping macro) either or not grabs the +%D namespace. We may extend this model later to a more +%D versatile one, using remapping. + +%D Parsing escapes is done by specific macros. For the +%D moment we assume that the sequence ends with an \type {>} +%D (which is definietly not the case for \type {CDATA}). + +\long\def\remapXMLescape#1#2>{} + +%D Processing instructions are remapped and only certain +%D cases are handled. + +\long\def\remapXMLprocess#1#2{\xmlp{procins/}{X}{#1}{#2}} + +%D This one is more efficient (although no one will notice +%D this since this macro is used seldom). + +\long\def\remapXMLprocess{\xmlp{procins/}{X}} + +%D Element need a bit more work; \type {#4} consumes spaces. + +% \def\remapXMLunknownONE#1#2% name args +% {\ifremapXMLunknown\remapXMLone{\s!unknown}{#1 #2}\fi} +% +% \def\remapXMLunknownTWO#1#2% name args +% {\ifremapXMLunknown\remapXMLtwo{\s!unknown}{#1 #2}\fi} +% +% \def\remapXMLunknownTHREE#1#2% name args +% {\ifremapXMLunknown\remapXMLthree{\s!unknown/}{#1 #2}\fi} +% +% \long\def\remapXMLelement#1#2 #3>#4% todo: we need to get rid of the end / +% {\ifcase\findendofXMLelement#2#3>% +% \if#1/% +% \expandafter\ifx\csname\@@XML\@@XMLmapping:#2:M\endcsname\relax +% \remapXMLunknownONE{#2}{}% +% \else +% \remapXMLone{#2}{}% +% \fi +% \else +% \expandafter\ifx\csname\@@XML\@@XMLmapping:#1#2:M\endcsname\relax +% \remapXMLunknownTWO{#1#2}{#3}% +% \else +% \remapXMLtwo{#1#2}{#3}% +% \fi +% \fi +% \else +% \expandafter\ifx\csname\@@XML\@@XMLmapping:#1#2:M\endcsname\relax +% \expandafter\ifx\csname\@@XML\@@XMLmapping:#1#2/:M\endcsname\relax +% \remapXMLunknownTHREE{#1#2}{#3}% +% \else +% \remapXMLthree{#1#2/}{#3}% +% \fi +% \else +% \remapXMLthree{#1#2}{#3}% +% \fi +% \fi#4} + +\def\remapXMLthreeempty#1% + {\remapXMLthree{#1/}} + +\def\remapXMLunknownONE#1#2% name args + {\ifremapXMLunknown\remapXMLone\s!unknown{#1 #2}\fi} + +\def\remapXMLunknownTWO#1#2% name args + {\ifremapXMLunknown\remapXMLtwo\s!unknown{#1 #2}\fi} + +\def\remapXMLunknownTHREE#1#2% name args + {\ifremapXMLunknown\remapXMLthreeempty\s!unknown{#1 #2}\fi} + +\long\def\remapXMLelement#1#2 #3>#4% todo: we need to get rid of the end / + {\ifcase\findendofXMLelement#2#3>% + \if#1/% + \expandafter\ifx\csname\@@XML\@@XMLmapping:#2:M\endcsname\relax + \@EA\remapXMLunknownONE + \else + \@EA\remapXMLone + \fi{#2}\empty + \else + \expandafter\ifx\csname\@@XML\@@XMLmapping:#1#2:M\endcsname\relax + \@EA\remapXMLunknownTWO + \else + \@EA\remapXMLtwo + \fi{#1#2}{#3}% + \fi + \else + \expandafter\ifx\csname\@@XML\@@XMLmapping:#1#2:M\endcsname\relax + \expandafter\ifx\csname\@@XML\@@XMLmapping:#1#2/:M\endcsname\relax + \@EAEAEA\remapXMLunknownTHREE + \else + \@EAEAEA\remapXMLthreeempty + \fi + \else + \@EA\remapXMLthree + \fi{#1#2}{#3}% + \fi#4} + +\unexpanded\def\xmlr#1#2{\csname\@@XML\@@XMLmapping:#1:#2\endcsname} +\unexpanded\def\xmlp#1#2{\csname\@@XML :#1:#2\endcsname} +\def \expandedxmlr#1#2{\csname\@@XML\@@XMLmapping:#1:#2\endcsname} + +\def\expandXMLremapping{\let\xmlr\expandedxmlr} + +\def\@@XMLremap{XMLremap} + +\def\remapXMLone#1#2% + {\ifcase\csname\@@XMLremap\csname\@@XML\@@XMLmapping:#1:M\endcsname\endcsname + \or % GCPA + \XMLeg\XMLeg + \or % GCP- + \XMLeg + \or % GC-A + \XMLeg\XMLeg + \or % GC-- + \XMLeg + \or % -CPA + \XMLeg + \or % -CP- + % + \or % -C-A + \XMLeg + \or % -C-- + % + \or % G--- + \XMLeg + \or % GLR- + \xmlr{#1}{R}\XMLeg + \or % -LR- + \xmlr{#1}{R}% + \fi} + +\def\remapXMLtwo#1#2% + {\ifcase\csname\@@XMLremap\csname\@@XML\@@XMLmapping:#1:M\endcsname\endcsname + \or % GCPA + \XMLbg\xmlr{#1}{X}{#2}\XMLbg + \or % GCP- + \XMLbg\xmlr{#1}{X}{#2}% + \or % GC-A + \XMLbg\xmlr{#1}{X}\XMLbg + \or % GC-- + \XMLbg\xmlr{#1}{X}% + \or % -CPA + \xmlr{#1}{X}{#2}\XMLbg + \or % -CP- + \xmlr{#1}{X}{#2}% + \or % -C-A + \xmlr{#1}{X}\XMLbg + \or % -C-- + \xmlr{#1}{X}% + \or % G--- + \XMLbg + \or % GLR- + \XMLbg\xmlr{#1}{L}% + \or % -LR- + \xmlr{#1}{L}% + \fi} + +\def\remapXMLthree#1#2% + {\ifcase\csname\@@XMLremap\csname\@@XML\@@XMLmapping:#1:M\endcsname\endcsname + \or % GCPA + \XMLbg\xmlr{#1}{X}{#2}\XMLbg\XMLeg\XMLeg + \or % GCP- + \XMLbg\xmlr{#1}{X}{#2}\XMLeg + \or % GC-A + \XMLbg\xmlr{#1}{X}\XMLbg\XMLeg\XMLeg + \or % GC-- + \XMLbg\xmlr{#1}{X}\XMLeg + \or % -CPA + \xmlr{#1}{X}{#2}\XMLbg\XMLeg + \or % -CP- + \xmlr{#1}{X}{#2}% + \or % -C-A + \xmlr{#1}{X}\XMLbg\XMLeg + \or % -C-- + \xmlr{#1}{X}% + \or % G--- + \XMLbg\XMLeg + \fi} + +\scratchtoks\@EA{\string{} \edef\XMLbg{\the\scratchtoks} +\scratchtoks\@EA{\string}} \edef\XMLeg{\the\scratchtoks} + +\chardef\XMLremapGCPA = 1 % {\command {arg} { } } +\chardef\XMLremapGCP = 2 % {\command {arg} } % +\chardef\XMLremapGCA = 3 % {\command { } } +\chardef\XMLremapGC = 4 % {\command } % +\chardef\XMLremapCPA = 5 % \command {arg} { } +\chardef\XMLremapCP = 6 % \command {arg} % +\chardef\XMLremapCA = 7 % \command { } +\chardef\XMLremapC = 8 % \command % +\chardef\XMLremapG = 9 % { } +\chardef\XMLremapGLR = 10 % { \bcom \ecom } +\chardef\XMLremapLR = 11 % \bcom \ecom + +%D The remapping is controlled by only a few definition +%D macros, that both deal with elements. We distinguish +%D between normal and empty elements. +%D +%D \starttyping +%D \remapXMLsequence [name] [result map] \unexpandablecommand +%D \remapXMLsequence [name] [result map] \unexpandablecommand +%D \stoptyping +%D +%D The \MATHML\ module demonstrates how these can be used. +%D The element is converted into a sequence with one or more +%D of the following components. +%D +%D \starttyping +%D { \command {parameters} {argument} } +%D \stoptyping +%D +%D The following combinations are supported. +%D +%D \starttabulate[|c|c|c|c|c|] +%D \NC GCPA \NC grouped \NC command \NC parameters \NC argument \NC \NR +%D \NC GCP \NC grouped \NC command \NC parameters \NC \NC \NR +%D \NC GCA \NC grouped \NC command \NC \NC argument \NC \NR +%D \NC GC \NC grouped \NC command \NC \NC \NC \NR +%D \NC CPA \NC \NC command \NC parameters \NC argument \NC \NR +%D \NC CP \NC \NC command \NC parameters \NC \NC \NR +%D \NC CA \NC \NC command \NC \NC argument \NC \NR +%D \NC C \NC \NC command \NC \NC \NC \NR +%D \NC G \NC grouped \NC \NC \NC \NC \NR +%D \stoptabulate +%D +%D Empty elements (singular ones) never get an argument, +%D which makes sense, since they have at most parameters. + +\def\remapXMLsequence{\doquadrupleargument\doremapXML []} +\def\remapXMLsingular{\doquadrupleargument\doremapXML[/]} + +\def\doremapXML[#1][#2][#3][#4]% + {\iffourthargument + \def\next{\dodoremapXML[#2][#1][#3][#4]}% + \else + \def\next{\dodoremapXML[\@@XMLmapping][#1][#2][#3]}% + \fi + \next} + +%\def\dodoremapXML[#1][#2][#3][#4]% class / name pattern +% {\doifinstringelse{LR}{#4} +% {\let\next\doremapXMLtwo} +% {\let\next\doremapXMLone}% +% \next[#1][#2][#3][#4]}% + +\def\dodoremapXML[#1][#2][#3][#4]% class / name pattern + {\doifinstringelse{LR}{#4}\doremapXMLtwo\doremapXMLone[#1][#2][#3][#4]} + +\def\doremapXMLone[#1][#2][#3][#4]#5% + {\setvalue{\@@XML#1:#3#2:M}{#4}% + \setvalue{\@@XML#1:#3#2:X}{#5}} + +\def\doremapXMLtwo[#1][#2][#3][#4]#5#6% + {\setvalue{\@@XML#1:#3:M}{#4}% + \setvalue{\@@XML#1:#3:L}{#5}% + \setvalue{\@@XML#1:#3:R}{#6}} + +\let\dowithentity\empty + +%D We handle processing instructions and unknown elements with: + +\remapXMLsingular [procins] [CPA] \normalparseXMLprocess +\remapXMLsingular [\s!unknown] [CPA] \doXMLunknownSI +\remapXMLsequence [\s!unknown] [CPA] \doXMLunknownSE + +\def\doXMLunknownSI#1#2{{\tttf[#1 #2]}} +\def\doXMLunknownSE#1#2{{\tttf[#1 #2]}} + +%D In a similar way, we can remap entities. + +\def\remapXMLentity#1;#2% + {\doremapXMLentity{#1}#2}% + +\def\doremapXMLentity + {\xmlrent} + +% \unexpanded\def\xmlrent#1% +% {\getXMLentity{#1}} +% +% replaced by: + +\unexpanded\def\xmlrent#1% + {\doXMLentity#1;} + +%D The remapping is taken care of by the following macro, +%D which takes three arguments. +%D +%D \starttyping +%D \XMLremapdata{before}{after}{content} +%D \stoptyping +%D +%D After the remapping, the content is executed (expanded) +%D under the normal \TEX\ catcode regime. The intermediate +%D result can be traced by turning on the following switch. + +\newif\iftraceXMLremapping + +\newtoks \everyXMLremapping + +\appendtoks + \defineXMLentity[tex-hash]{\letterhash}% + \defineXMLentity[tex-bar]{\myspecialnormalvert}% +\to \everyXMLremapping + +\def\setnormalXMLentities% will change ! ! ! ! ! + {\defineXMLentity[tex-hash]\letterhash + \defineXMLentity[tex-dollar]\letterdollar + \defineXMLentity[tex-percent]\letterpercent + \defineXMLentity[tex-backslash]\letterbackslash + \defineXMLentity[tex-hat]\letterhat + \defineXMLentity[tex-underscore]\letterunderscore + \defineXMLentity[tex-leftbrace]\letterbgroup + \defineXMLentity[tex-rightbrace]\letteregroup + \defineXMLentity[tex-bar]\letterbar} + +\let\XMLremappedpar\empty + +%D Here we implement the second step in the element grabber. + +\long\def\XMLremapdata + {\dosingleempty\doXMLremapdata} + +\long\def\doXMLremapdata[#1]#2#3#4% + {\bgroup + \startXMLmapping[#1]% + % enable unknown elements (should be macro) + \doifsomething{#1} + {\doifdefinedelse{\@@XML#1:\s!unknown:M} + {\remapXMLunknowntrue}{\remapXMLunknownfalse}}% + % + \pushmacro\doXMLentity % needed ? + % this will change, proper split in element itself + \ifx\currentXMLnamespace\empty + \let\parseXMLelement\remapXMLelement + \else + % here we need to get rid of the namespace; we also + % have to preserve the leading / if present + \@EA\long\@EA\def\@EA\parseXMLelement\@EA + ##\@EA1\currentXMLnamespace:{\remapXMLelement##1}% + % ##2 removes leading spaces + \fi + % + \let\parseXMLescape \remapXMLescape + \let\parseXMLprocess\remapXMLprocess + % + \let\doXMLentity \remapXMLentity + % + \enableXML % sets entities + \enableXMLexpansion + \let\par\XMLremappedpar + \the\everyXMLremapping + %\ignorelines + \catcode\tabasciicode \spacecatcode + \catcode\endoflineasciicode\spacecatcode + \catcode\formfeedasciicode \spacecatcode + \catcode\endoffileasciicode\spacecatcode + \pushmacro\unicodechar + \let\unicodechar\relax + \xdef\remappedXMLdata{#4\empty}% + \popmacro\unicodechar + \let\par\endgraf + \popmacro\doXMLentity % needed ? + \disableXMLexpansion + \catcode`\{=\@@begingroup + \catcode`\}=\@@endgroup + \catcode`\\=\@@escape + \iftraceXMLremapping + \ifmmode\vbox\fi\bgroup + \defconvertedcommand\ascii\remappedXMLdata + \tttf\veryraggedright\ascii\par + \writestatus{xml-remap}{\ascii}% + \egroup + \fi + #2\scantokens\@EA{\remappedXMLdata\empty\empty}#3% + \stopXMLmapping + \egroup} + +% testcase: +% +% aap‒noot coördinatie – één +% +% \startXMLdata +% aap‒noot coördinatie – één +% <formula><math><mtext>aap‒noot coördinatie – één</mtext></math></formula> +% \stopXMLdata +% +% weird case: +% +% \chardef\XMLtokensreduction\zerocount +% \startXMLdata +% <formula><math><mtext>\"{a}\"{o}\"{u}\v{c}\v{s}\v{z}</mtext></math></formula> +% \stopXMLdata +% +% \chardef\XMLtokensreduction\plustwo +% \startXMLdata +% <formula><math><mtext>\"{a}\"{o}\"{u}\v{c}\v{s}\v{z}</mtext></math></formula> +% \stopXMLdata + +% rename to better names + +\newtoks \XMLRtoks +\newcount \nofXMLRchildren + +\def\naturalxmlr#1#2{\getvalue{\@@XML\@@XMLmapping:#1:#2}} + +\def\ignoreXMLRelement#1#2{} +\def\normalXMLRelement#1#2{#2} + +\let\nextXMLRelement \empty +\let\firstXMLRelement \empty +\let\secondXMLRelement\empty + +% \def\withnextXMLRelement#1% +% {\pushmacro\dowithnextXMLRelement +% \def\dowithnextXMLRelement##1##2##3##4##5% +% {\popmacro\dowithnextXMLRelement +% \def\nextXMLRelement{##1{##2}{##3}{##4}{##5}}% +% #1}% +% \doifnextcharelse\empty\empty\dowithnextXMLRelement} +% +% better and faster: + +\def\dowithnextXMLRelement#1#2#3#4#5#6% + {\def\nextXMLRelement{#2{#3}{#4}{#5}{#6}}#1}% + +\def\withnextXMLRelement#1% + {\doifnextcharelse\empty\empty{\dowithnextXMLRelement{#1}}} + +\def\withnexttwoXMLRelements#1% + {\pushmacro\firstXMLRelement + \pushmacro\secondXMLRelement + \withnextXMLRelement + {\let\firstXMLRelement\nextXMLRelement + \withnextXMLRelement + {\let\secondXMLRelement\nextXMLRelement + #1% + \popmacro\secondXMLRelement + \popmacro\firstXMLRelement}}} + +\def\withnextthreeXMLRelements#1% korter, met two + {\pushmacro\firstXMLRelement + \pushmacro\secondXMLRelement + \pushmacro\thirdXMLRelement + \withnextXMLRelement + {\let\firstXMLRelement\nextXMLRelement + \withnextXMLRelement + {\let\secondXMLRelement\nextXMLRelement + \withnextXMLRelement + {\let\thirdXMLRelement\nextXMLRelement + #1% + \popmacro\thirdXMLRelement + \popmacro\secondXMLRelement + \popmacro\firstXMLRelement}}}} + +\def\doifXMLRchildelse#1#2#3#4% + {\pushmacro\xmlr + \def\next{#4}% + \def\xmlr##1##2##3##4% the / should be sorted out in the mapper + {\rawdoifinsetelse{##1}{#1} + {\def\next{#3}} + {\doif{##1}{#1/}{\def\next{#3}}}}% + #2\empty + \popmacro\xmlr + \next} + +\def\doifXMLRchild#1#2#3% + {\pushmacro\xmlr + \let\next\empty + \def\xmlr##1##2##3##4% the / should be sorted out in the mapper + {\rawdoifinsetelse{##1}{#1} + {\def\next{#3}} + {\doif{##1}{#1/}{\def\next{#3}}}}% + #2\empty + \popmacro\xmlr + \next} + +\def\encapsulateXMLRchild#1#2#3#4#5% + {\pushmacro\xmlr + \def\xmlr##1##2##3##4% + {\doifelse{##1}{#1} + {\def\next{\doencapsulateXMLRchild{#2}{#3}{#4}{##4}}} + {\let\next\empty}% + \next}% + #5\empty + \popmacro\xmlr} + +\def\encapsulateXMLRchildren#1#2#3#4#5% + {\pushmacro\xmlr + \pushmacro\betweenXMLRchild + \def\betweenXMLRchild{\def\betweenXMLRchild{#3}}% + \def\xmlr##1##2##3##4% + {\rawdoifinsetelse{##1}{#1} + {\pushmacro\xmlr + \let\xmlr\naturalxmlr + \betweenXMLRchild\xmlr{##1}{##2}{##3}{##4}% + \popmacro\xmlr} + {}}% + #2#5\empty#4% + \popmacro\betweenXMLRchild + \popmacro\xmlr} + +\def\doencapsulateXMLRchild#1#2#3#4% + {\pushmacro\xmlr + \pushmacro\betweenXMLRchild + \def\betweenXMLRchild{\def\betweenXMLRchild{#2}}% + \def\xmlr##1##2##3##4% + {\pushmacro\xmlr + \let\xmlr\naturalxmlr + \betweenXMLRchild\xmlr{##1}{##2}{##3}{##4}% + \popmacro\xmlr}% + #1#4\empty#3% + \popmacro\betweenXMLRchild + \popmacro\xmlr} + +\let\encapsulateXMLR\doencapsulateXMLRchild + +\def\withnextXMLRelementelse#1#2% + {\def\xdowithnextXMLRelement##1##2##3##4##5% + {\def\nextXMLRelement{##1{##2}{##3}{##4}{##5}}#1}% + \def\xnowithnextXMLRelement% + {\let\nextXMLRelement\empty#2}% + \doifnextcharelse\xmlr\xdowithnextXMLRelement\xnowithnextXMLRelement} + +\def\encapsulatenextXMLRelements#1#2#3#4% oude bewaren + {\pushmacro\betweenXMLRchild + \pushmacro\afterXMLRchild + \def\betweenXMLRchild{#1\def\betweenXMLRchild{#2}}% + \let\afterXMLRchild\empty + \withnextXMLRelementelse + {\betweenXMLRchild + \def\afterXMLRchild{#3}% + \nextXMLRelement + \doifnextcharelse\empty\xnowithnextXMLRelement\xdowithnextXMLRelement} + {\afterXMLRchild + \popmacro\afterXMLRchild + \popmacro\betweenXMLRchild}% + #4} + +\def\collectXMLRchild#1#2% + {\XMLRtoks\emptytoks + \pushmacro\xmlr + \def\xmlr##1##2##3##4% + {\doif{##1}{#1}{\appendtoks##4\to\XMLRtoks}}% + #2\empty + \popmacro\xmlr} + +\def\doifelseXMLRneighbors#1#2% + {\XMLRtoks\emptytoks + \pushmacro\xmlr + \donefalse + \let\prevXMLRchild\empty + \def\xmlr##1##2##3##4% + {\doif{##1}{#1}{\doif{##1}\prevXMLRchild{\donetrue}}% + \def\prevXMLRchild{##1}}% + #2\empty + \popmacro\xmlr + \ifdone + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\def\collectbetweenXMLRchild#1#2#3% + {\XMLRtoks\emptytoks + \pushmacro\xmlr + \pushmacro\betweenXMLRchild + \def\betweenXMLRchild{\def\betweenXMLRchild{\appendtoks#2\to\XMLRtoks}}% + \def\xmlr##1##2##3##4% + {\rawdoifinsetelse{##1}{#1} + {\betweenXMLRchild\appendtoks\xmlr{##1}{##2}{##3}{##4}\to\XMLRtoks}{}}% + #3\empty + \popmacro\betweenXMLRchild + \popmacro\xmlr} + +\def\dorawcollectbetweenXMLR#1#2% + {\pushmacro\xmlr + \pushmacro\betweenXMLRchild + \def\betweenXMLRchild{\def\betweenXMLRchild{#1}}% + \def\xmlr##1##2##3##4% + {\betweenXMLRchild\appendtoks\xmlr{##1}{##2}{##3}{##4}\to\XMLRtoks}% + #2\empty + \popmacro\betweenXMLRchild + \popmacro\xmlr} + +\def\rawcollectbetweenXMLR% + {\XMLRtoks\emptytoks\dorawcollectbetweenXMLR} + +\def\docollectbetweenXMLR#1% + {\dorawcollectbetweenXMLR{\appendtoks#1\to\XMLRtoks}} + +\def\collectbetweenXMLR% + {\XMLRtoks\emptytoks\docollectbetweenXMLR} + +\def\processXMLRchildren#1% + {\pushmacro\xmlr + \let\xmlr\naturalxmlr + #1\empty + \popmacro\xmlr} + +\def\processXMLRchild#1#2% slow but more versatile + {\pushmacro\xmlr + \XMLRtoks\emptytoks + \def\xmlr##1##2##3##4% + {\rawdoifinsetelse{##1}{#1} + {\appendtoks\xmlr{##1}{##2}{##3}{##4}\to\XMLRtoks}{}}% + #2% + \popmacro\xmlr + \the\XMLRtoks\empty} + +\def\countXMLRchildren#1% + {\pushmacro\xmlr + \nofXMLRchildren=0 + \def\xmlr##1##2##3##4{\advance\nofXMLRchildren\plusone} + #1\empty + \popmacro\xmlr} + +\def\countXMLRchild#1#2% + {\pushmacro\xmlr + \nofXMLRchildren=0 + \def\xmlr##1##2##3##4% + {\rawdoifinsetelse{##1}{#1}{\advance\nofXMLRchildren\plusone}{}} + #2\empty + \popmacro\xmlr} + +\def\installXMLunknownremapping + {\remapXMLsingular[\s!unknown][CPA]\doXMLunknownSI + \remapXMLsequence[\s!unknown][CPA]\doXMLunknownSE} + +\bgroup \catcode`<=\active + +\gdef\revertXMLremapping + {\gdef\doXMLunknownSE##1##2{<##1>##2</##1>}% + \gdef\doXMLunknownSI##1##2{<##1>}} + +\gdef\unmapXMLdata#1#2% todo: singular, evt ##2 space ervoor en ##1##2 + {\bgroup + \revertXMLremapping + \expandXMLremapping % now we can roll back + \setnormalXMLhandler % using the normal parser + \resetXMLmapping % and leaving the mapping namespace + \xdef\unmappedXMLdata{#2}% recreate the original + \enableXMLelements % enable normal handler + \unmappedXMLdata % off we go ... + \egroup} + +\egroup + +\protect \endinput |