summaryrefslogtreecommitdiff
path: root/tex/context/base/xtag-ini.tex
diff options
context:
space:
mode:
authorHans Hagen <pragma@wxs.nl>2002-01-11 00:00:00 +0100
committerHans Hagen <pragma@wxs.nl>2002-01-11 00:00:00 +0100
commit736de6a312c37fbb8cea65cf0a86eda7dbbe0575 (patch)
treead6691db97ee31450f9ca5b30a90a22df067331b /tex/context/base/xtag-ini.tex
parent398264e8338d79fc389c76f0a1f0b30e4442f4e3 (diff)
downloadcontext-736de6a312c37fbb8cea65cf0a86eda7dbbe0575.tar.gz
stable 2002.01.11
Diffstat (limited to 'tex/context/base/xtag-ini.tex')
-rw-r--r--tex/context/base/xtag-ini.tex1949
1 files changed, 1387 insertions, 562 deletions
diff --git a/tex/context/base/xtag-ini.tex b/tex/context/base/xtag-ini.tex
index 970f065df..97853ed45 100644
--- a/tex/context/base/xtag-ini.tex
+++ b/tex/context/base/xtag-ini.tex
@@ -11,20 +11,32 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\beginTEX
+% csnames
+
+\beginTEX
\writestatus{XML}{sorry, XML is only supported in (pdf)etex}
\def\startXMLdefinitions{\gobbleuntil\stopXMLdefinitions}
- \endinput
-\endTEX
+ \endinput
+\endTEX
+
+\writestatus{loading}{Context XML Macros (initialization)}
+
+% XMLelse -> elseXML
+
+%D This module is highly optimized for speed, which sometimes
+%D reads to rather unreadable code. Sorry for this.
+
+\def\gobblespacetokens % will go to syst-ext.tex + speed up
+ {\doifnextcharelse\empty\donothing\donothing} % no {}\do\do !
\beginETEX XML
\bgroup \obeylines
- \gdef\startXMLdefinitions%
- {\bgroup\obeylines\dostartXMLdefinitions}
+ \gdef\startXMLdefinitions%
+ {\bgroup\obeylines\dostartXMLdefinitions}
- \gdef\dostartXMLdefinitions #1
+ \gdef\dostartXMLdefinitions #1
{\egroup\doifsomething{#1}{\writestatus{XML}{loading #1 support}}}
\global\let\stopXMLdefinitions\relax
@@ -42,16 +54,17 @@
%D Like it or not, this module deals with angle bracketed
%D input. Processing \XML\ alike input in \CONTEXT\ has been
-%D possible since 1994, but several methods ran in parallel
-%D and were implemented in modules like \type {m-sgml}.
+%D possible since 1995, and till 2000 several methods ran in
+%D parallel. These were implemented in modules like the semi
+%D public \type {m-sgml}.
%D
-%D There is no one optimal solution for processing \XML\ data.
+%D There is not one optimal solution for processing \XML\ data.
%D The oldest method was based on a very simple preprocessor
-%D written in \PERL: \type {<command>} was converted into
-%D \type {\begSGML[command]} and optional parameters were
-%D passed.
+%D written in \MODULA\ and later \PERL: \type {<command>} was
+%D converted into \type {\begSGML[command]} and optional
+%D parameters were passed.
%D
-%D A second method is to use a \PERL\ or \XSL\ transformation
+%D A second method uses a \PERL\ or \XSL\ transformation
%D script that produces \CONTEXT\ commands. This method is
%D much slower, mainly because the whole document is read into
%D memory and a document tree is to be build. The advantage is
@@ -60,34 +73,60 @@
%D The third method uses a basic parser written in the \TEX\
%D language, and apart from a few pitfalls, this method is
%D clean and efficient, but not always robust. Because errors
-%D in the input are not catched on forhand, processing in
+%D in the input are not catched on forehand, processing in
%D \TEX\ may fail due to errors. But, given that a document
%D can be validated on forehand, this is no big problem.
%D
-%D Each method has it's advantage, but especially the third
+%D Each method has its advantage, but especially the third
%D method puts some demands on \CONTEXT, since no interference
%D between the parser and the core commands may occur. What
%D method is used, depends on the situation.
%D
%D All three methods introduce some problems in interfacing to
%D core \CONTEXT\ functionality. This is due to the fact that
-%D sometimes we want to typeset content directly, while on
+%D sometimes we want to typeset content directly, while in
%D other cases we just want to pick up data for later usage,
%D either or not using delimited arguments. And, when moving
%D data around, there is always the expansion problem to deal
%D with.
-%D
+%D
+%D As can be expected, we have to map begin and end tags onto
+%D \CONTEXT's start- and stopcommands. This is the easy part.
+%D When we have to pass the content of an element to a macro
+%D as argument, we need to do a delimited grab. Such mappings
+%D are not that hard to implement and were part of \type
+%D {m-sgml.tex} already. New in this core module is nested
+%D grabbing. Also new here is the support for namespaces and
+%D extensive attribute handling. On the other hand, recursive
+%D traceback of attributes is no longer supported. Because
+%D this feature was not really used, we can hereby safely we
+%D declare the \type {m-sgml.tex} module obsolete.
+%D
%D In order to be able to incorporate \XML\ style definitions
%D into basic \TEX\ styles, we will provide some basic
-%D functionality in the core itself.
+%D functionality in the core itself. Some of the functionality
+%D can be set up with this general command. We use a token
+%D list register to handle post||setup actions. This permits
+%D us to extend this command.
+
+\unprotect
+
+\newtoks\aftersetupXMLprocessing
+
+\def\setupXMLprocessing
+ {\dosingleargument\dosetupXMLprocessing}
+
+\def\dosetupXMLprocessing[#1]%
+ {\getparameters[\??xp][#1]\the\aftersetupXMLprocessing}
+
+\protect
%D We will be dealing with elements, which means that we have
%D to take care of \type {<this>} and \type {</that>}, but
-%D also with \type {<such/>} and \type {<so />}. In due time
-%D this module will deal with all these animals in a
-%D convenient way. In some cases the upper and lowercase
-%D alternatives need to be dealt with, although this is not
-%D realy needed since XML is case sensitive.
+%D also with \type {<such/>} and \type {<so />}. In some cases
+%D the upper and lowercase alternatives need to be dealt with,
+%D although this is not realy needed since XML is case
+%D sensitive.
%D
%D We also have to handle entities, like \type {&you;} and
%D \type {&me;}. These are quite easy to deal with and need to
@@ -100,47 +139,47 @@
%D Since we have to handlers for each element and entity, we
%D will create a few namespaces. Special care has to be
%D given to preformated code.
+%D
+%D There are two namespace mechanisms in place: one for
+%D \TEX, and one for \XML. The later mechanism permits
+%D remapping and ignoring.
\unprotect
\def\@@XML {XML:}
-\def\@@XMLentity {\@@XML ent}
-\def\@@XMLelement {\@@XML ele}
-\def\@@XMLvariable {\@@XML var}
-\def\@@XMLvalue {\@@XML val}
-\def\@@XMLpars {\@@XML par}
-\def\@@XMLdata {\@@XML dat}
-\def\@@XMLcode {\@@XML cod}
-\def\@@XMLinstruction {\@@XML ins}
-\def\@@XMLmap {\@@XML map}
-\def\@@XMLlist {\@@XML lst}
+\def\@@XMLentity {\@@XML ent} % &crap;
+\def\@@XMLelement {\@@XML ele} % <this> </this> <that/>
+\def\@@XMLvariable {\@@XML var} % key="val"
+\def\@@XMLvalue {\@@XML val} % key="val"
+\def\@@XMLpars {\@@XML par} %
+\def\@@XMLdata {\@@XML dat} % mem buffer
+\def\@@XMLcode {\@@XML cod} % named mem buffers
+\def\@@XMLinstruction {\@@XML ins} % <?
+\def\@@XMLmap {\@@XML map} % mapping on context attr
+\def\@@XMLlist {\@@XML lst} %
+\def\@@XMLnamespace {\@@XML nam} % namespace:element
+\def\@@XMLurlspace {\@@XML url} %
+\def\@@XMLescape {\@@XML esc} % <!
+\def\@@XMLdepth {\@@XML dep} % used to track nesting
+\def\@@XMLdopth {\@@XML dop} % used to track nesting
+\def\@@XMLsave {\@@XML sav} % namespace for saved elements
\newtoks\XMLtoks
\newtoks\XMLresetlist
-\chardef\XMLargumentmode=0
-
-\newif\ifignoreXMLcase
\newif\ifignoreXMLspaces
\newif\iffixedXMLfont
+\newif\iftraceXMLelements
+\newif\ifprocessingXML
-%D \macros
-%D {compound}
-%D
-%D We will overload the already active \type {|} so we have
-%D to save its meaning in order to be able to use this handy
-%D macro.
-%D
-%D \starttypen
-%D so test\compound{}test can be used instead of test||test
-%D \stoptypen
+\newcount\XMLlevel % scratchcounter
+\newcount\XMLdepth % used here
-\let\docompound=| \def\compound#1{\docompound#1|}
+\newtoks\everyenableXML
%D We will implement the parser by making a few characters
%D active. For that reason we also have to save their
-%D original meaning. The core handlers are \type
-%D {\doXMLentity} and \type {\doXMLelement}.
+%D original meaning.
%D \macros
%D {enableXML}
@@ -156,34 +195,46 @@
\catcode`\.=\@@escape
.catcode`.B=.@@begingroup
.catcode`.E=.@@endgroup
-
-.catcode`.&=.@@active .gdef.letterampersand B.string&E
-.catcode`.<=.@@active .gdef.letterless B.string<E
-
-.catcode`.#=.@@active .gdef.letterhash B.string#E
-.catcode`.$=.@@active .gdef.letterdollar B.string$E
-.catcode`.%=.@@active
-.catcode`.\=.@@active .gdef.letterbackslash B.string\E
-.catcode`.^=.@@active .gdef.letterhat B.string^E
-.catcode`._=.@@active .gdef.letterunderscore B.string_E
-.catcode`.{=.@@active .gdef.letterbgroup B.string{E
-.catcode`.}=.@@active .gdef.letteregroup B.string}E
-.catcode`.|=.@@active .gdef.letterbar B.string|E
-.catcode`.~=.@@active .gdef.lettertilde B.string~E
-
-.gdef.enableXMLexpansion
+.catcode`.P=.@@parameter
+
+.catcode`.&=.@@active * .gdef.letterampersand B.string&E
+.catcode`.<=.@@active * .gdef.letterless B.string<E
+ * .gdef.lettermore B.string>E
+.catcode`.#=.@@active * .gdef.letterhash B.string#E
+.catcode`.$=.@@active * .gdef.letterdollar B.string$E
+.catcode`.%=.@@active * .gdef.letterpercent B.string%E
+.catcode`.\=.@@active * .gdef.letterbackslash B.string\E
+.catcode`.^=.@@active * .gdef.letterhat B.string^E
+.catcode`._=.@@active * .gdef.letterunderscore B.string_E
+.catcode`.{=.@@active * .gdef.letterbgroup B.string{E
+.catcode`.}=.@@active * .gdef.letteregroup B.string}E
+.catcode`.|=.@@active * .gdef.letterbar B.string|E
+.catcode`.~=.@@active * .gdef.lettertilde B.string~E
+
+.gdef.enableXMLexpansion
B.def<B.doXMLelementE.let&=.doXMLentityE
-.gdef.disableXMLexpansion
+.gdef.disableXMLexpansion
B.unexpanded.def<B.doXMLelementE.let&=.doXMLentityE
-.gdef.enableXML*
+* internally the # becomes two #'s (before expanding, during
+* the parsing stage) which is why we let the first # gobble
+* the second one
+*
+* since this only takes place when reading arguments, as in
+* \startXMLdata ... cum, suis, we can take place of it
+* there; this is needed because reading from file goes wrong
+* (eating up argument)
+
+.unexpanded.gdef.enableXML*
B.catcode`.!=.@@other*
- .catcode`.?=.@@other*
+ .catcode`.?=.@@other*
.catcode`.&=.@@active .let&=.doXMLentity*
.catcode`.<=.@@active .unexpanded.def<B.doXMLelementE*
- .catcode`.>=.@@other*
- .catcode`.#=.@@active .def#B&tex-hash;E*
+ .catcode`.>=.@@other .catcode`."=.@@other*
+ .catcode`./=.@@other .catcode`.'=.@@other*
+ *catcode`.#=.@@active .def#PP1B&tex-hash;E* gobbles its own dup
+ .catcode`.#=.@@active .def#B&tex-hash;E*
.catcode`.$=.@@active .def$B&tex-dollar;E*
.catcode`.%=.@@active .def%B&tex-percent;E*
.catcode`.\=.@@active .def\B&tex-backslash;E*
@@ -192,18 +243,35 @@
.catcode`.{=.@@active .def{B&tex-leftbrace;E*
.catcode`.}=.@@active .def}B&tex-rightbrace;E*
.catcode`.|=.@@active .def|B&tex-bar;E*
- .catcode`.~=.@@other* active .def~B&tex-tilde;E*
- .relax* needed for successive .if's
+ .catcode`.~=.@@other *def~B&tex-tilde;E*
+ .processingXMLtrue
+ .the.everyenableXML
E
-.gdef.enableXMLelements*
- B.catcode`.<=.@@active .unexpanded.def<B.doXMLelementE*
- .catcode`.>=.@@other*
- .relax* needed for successive .if's
+* The following macro can be invokes when reading from
+* an auxiliary file.
+
+.unexpanded.gdef.enableXMLelements*
+ B.catcode60=.@@active * .catcode`.<=.@@active
+ .catcode62=.@@other * .catcode`.>=.@@other
+ .unexpanded.def<B.doXMLelementE*
+ .processingXMLtrue
+ E
+
+.unexpanded.gdef.disableXMLelements*
+ B.catcode60=.@@active * .catcode`.<=.@@active
+ .catcode62=.@@other * .catcode`.>=.@@other
+ .let<.relax * new
+ .processingXMLfalse
E
+.global.let<.relax * new
+.global.let&.relax * new
+
.egroup
+\def\disableXML{\setnormalcatcodes\processingXMLfalse}
+
%D An element can be singular or paired. A singular element is
%D called an empty element. The following definitions are
%D equivalent:
@@ -265,45 +333,83 @@
%D to determine if we're dealing with a comment or processing
%D instruction. We need a bit of grouping because we have to
%D mess up with catcodes. We probably have to treat a few
-%D more catcode and first character cases. We need to use
-%D \type {\begingroup} here, otherwise we get funny spaces in
-%D math.
+%D more catcode and first character cases. We need to use
+%D \type {\begingroup} here, otherwise we get funny spaces in
+%D math.
-\protect
+%D Maybe I will remove grouping here and introduce \type
+%D {\obeyXMLlines}.
-\long\def\doXMLelement#1%
- {\begingroup % maybe tab and space needs some treatment too: \catcode`\ =10 % \@@space
- \catcode`\^^M=10
- \if#1!\let\next \xdoXMLelement \else
- \if#1?\let\next \ydoXMLelement \else
- \let\next \zdoXMLelement \fi\fi
- \next#1}
-
-%D By using a few {\expandafter}'s we can us a \type {\next}
+%D By using a few {\expandafter}'s we can avoid a \type {\next}
%D construction. We could speed the first char test up a bit
%D by using an installer and something \typ {\getvalue
-%D {#1doXMLelement}} (todo).
+%D {#1doXMLelement}} (todo).
+
+\protect % we need an normal ! ?
+
+% \long\def\doXMLelement#1%
+% {\if#1!\expandafter \xparseXMLescape \else
+% \if#1?\expandafter\expandafter\expandafter \xparseXMLprocess \else
+% \expandafter\expandafter\expandafter \xparseXMLelement \fi\fi
+% #1}
+
+\def\expandthree{\expandafter\expandafter\expandafter}
\long\def\doXMLelement#1%
- {\begingroup % maybe tab and space needs some treatment too: \catcode`\ =10 % \@@space
- \catcode`\^^M=10\relax
- \if#1!\expandafter \xdoXMLelement \else
- \if#1?\expandafter\expandafter\expandafter \ydoXMLelement \else
- \expandafter\expandafter\expandafter \zdoXMLelement \fi\fi
+ {\if#1!\expandafter \xparseXMLescape \else
+ \if#1?\expandthree \xparseXMLprocess \else
+ \expandthree \xparseXMLelement \fi\fi
#1}
-%D The (yet experimental) \type {CDATA} parser is implemented
-%D on top of the verbatim environment.
+% does it end with ? or ?>
+
+\long\def\xparseXMLescape !#1 {\parseXMLescape{#1}}
+\long\def\xparseXMLprocess ?#1 #2>{\parseXMLprocess{#1}{#2}}
+\long\def\xparseXMLelement #1>{\parseXMLelement #1 >}
+
+% this kind of optimizations are only faster in a more
+% extensive if tree combined with equally spread occurance of
+% #1 (also tested for arguments)
+%
+% \long\def\doXMLelement#1%
+% {\csname<\if#1!!\else\if#1??\else.\fi\fi>\endcsname#1}
+%
+% \long\setvalue{<!>}!#1 {\parseXMLescape{#1}}
+% \long\setvalue{<?>}?#1 {\parseXMLprocess{#1}}
+% \long\setvalue{<.>}#1>{\parseXMLelement#1 >}
+
+%D The escape handler takes care of the fuzzy \type {<!}
+%D constructs. Unfortunately, we need to catch \type {<--text}
+%D too, so we need another handler:
+
+\long\def\xparseXMLescape !#1#2%
+ {\if#1-%
+ \if#2-%
+ \expandafter\expandafter\expandafter\xxparseXMLescape
+ \else
+ \expandafter\expandafter\expandafter\xyparseXMLescape
+ \fi
+ \else
+ \expandafter\xyparseXMLescape
+ \fi#1#2}
+
+\long\def\xxparseXMLescape --#1{\parseXMLescape{--}#1}
+\long\def\xyparseXMLescape #1 {\parseXMLescape{#1}}
+
+%D Now the real work can begin.
+
+\unprotect
-\long\def\xdoXMLelement !#1 % !-- --> or !xyz >
- {\endgroup
- \doifelse{#1}{--}
- {\long\def\nextelement{\gobbleuntil{-->}}}
- {\doifelse{#1}{[CDATA[}
- {\long\def\nextelement{\skipfirstverbatimlinefalse
- \processtaggeddisplayverbatim{]]>}}}
- {\long\def\nextelement{\gobbleuntil{>}}}}%
- \nextelement}
+\def\defineXMLescape[#1]#2%
+ {\unspaceargument#1\to\ascii % get rid of {}, like in {CDATA[}
+ \long\setvalue{\@@XMLescape:\ascii}{#2}}
+
+\def\parseXMLescape#1% #2> parsing takes place in macros
+ {\executeifdefined{\@@XMLescape:#1}{\csname\@@XMLescape:\s!default\endcsname}}
+
+\let\normalparseXMLescape \parseXMLescape
+\let\normalparseXMLelement\parseXMLelement
+\let\normalparseXMLprocess\parseXMLprocess
%D In our case, processing instructions are only needed if
%D we want specific \CONTEXT\ support. This may be useful in
@@ -311,183 +417,620 @@
%D application. We will implement a \CONTEXT\ code handler
%D later.
-\long\def\ydoXMLelement#1 #2?>% ?target ?>
- {\endgroup\dodoXMLprocessor{#1}{#2}}
+%D The processing instructions handler is implemented as
+%D follows.
-%D The normal elements are handled by \type {\dodoXMLelement}.
+\long\def\defineXMLprocessor[#1]#2%
+ {\long\setvalue{\@@XMLinstruction:#1}{#2}}
-\long\def\zdoXMLelement#1>%
- {\endgroup\dodoXMLelement#1 >}
+% \def\parseXMLprocess#1#2%
+% {\executeifdefined{\@@XMLinstruction:#1}\gobbleoneargument{#2}}
-%D Now we switch to unprotected mode again.
+%D Because we support \type {.. ?>} as well as \type {.. >}
+%D end||of||pi situations, we need to clean up the ending
+%D \type {?}.
-\unprotect
+\protect
-%D The processing instructions handler is implemented as
-%D follows.
+\long\def\cleanupXMLprocess#1%
+ {\docleanupXMLprocess#1 ? \relax}
+
+\long\def\docleanupXMLprocess#1? #2\relax
+ {\def\currentXMLprocess{#1}}
+
+\unprotect
+
+\def\parseXMLprocess#1#2%
+ {\cleanupXMLprocess{#2}%
+ %\convertcommand\currentXMLprocess\to\ascii
+ %\writestatus{xml-process}{\ascii}
+ \expanded
+ {\executeifdefined
+ {\@@XMLinstruction:#1}
+ \noexpand\gobbleoneargument
+ {\expandafter\noexpand\currentXMLprocess}}}
+
+%D Next we will implement the normal element handler. This
+%D piece of code is complicated by the fact that we need to
+%D handle namespaces.
+
+\let\currentXMLarguments \empty
+\let\currentXMLelement \empty % name
+\let\currentXMLidentifier\empty % name or name/
+\let\currentXMLnamespace \empty % the (remapped) namespace
+\let\originalXMLnamespace\empty % the unremapped namespace
+\let\rawXMLidentifier \empty
-\long\def\dodoXMLprocessor#1%
- {\ifundefined{\@@XMLinstruction:#1}%
- \let\next\gobbleoneargument
+\def\rawXMLnamespace
+ {\ifx\currentXMLnamespace\empty\else\currentXMLnamespace:\fi}
+
+\def\rawXMLelement{\rawXMLnamespace\rawXMLidentifier}
+
+%D The following token list register provided the user a hook
+%D for extensions.
+
+\newtoks\everyXMLelement
+
+%D We try to keep track of the nature of an element. This
+%D flag can be used for special purposes (as in the pretty
+%D printing macros).
+
+\chardef\kindofXMLelement=0
+
+\chardef\beginXMLtag=1
+\chardef\endXMLtag =2
+\chardef\emptyXMLtag=3
+
+%D We do a rather hard coded scan for the namespace attribute. This
+%D is needed because its value determines further namespace related
+%D actions.
+
+\def\openXMLargument{ /}
+
+\long\def\parseXMLelement#1#2 #3>%
+ {\def\currentXMLarguments{#3}% including end /
+ \if#1/%
+ \chardef\kindofXMLelement\endXMLtag
+ \def\currentXMLelement{#2}%
\else
- \def\next{\getvalue{\@@XMLinstruction:#1}}%
+ \docleanupXMLelement#1#2/\empty\relax
+ \fi
+ \ifx\currentXMLarguments\openXMLargument
+ \chardef\kindofXMLelement\emptyXMLtag
\fi
- \next}
+ \@EA\splitoffXMLnamespace\currentXMLelement::\relax
+ \ifcase\kindofXMLelement
+ % can't happen
+ \or
+ % begintag or emptytag with arguments or space before /
+ \the\everyXMLelement % only for begin/empty tag !
+ \ifx\currentXMLarguments\empty \else
+ \dogetXMLarguments\rawXMLelement#3>%
+ \fi
+ \or
+ % no arguments
+ \or
+ % empty element without arguments (but possible presets)
+ \the\everyXMLelement
+ \fi
+ \ifcase\kindofXMLelement\or
+ \let\currentXMLidentifier \rawXMLidentifier
+ \edef\currentXMLfullidentifier {\rawXMLelement }%
+ \or
+ \edef\currentXMLidentifier {/\rawXMLidentifier }%
+ \edef\currentXMLfullidentifier{/\rawXMLelement }%
+ \or
+ \edef\currentXMLidentifier {\rawXMLidentifier/}%
+ \edef\currentXMLfullidentifier {\rawXMLelement /}%
+ \fi
+ \iftraceXMLelements\traceXMLelement\fi
+ \executeXMLelement}
+
+\long\def\docleanupXMLelement#1/#2#3\relax
+ {\def\currentXMLelement{#1}% watch out: \empty == begin or empty tag
+ \chardef\kindofXMLelement\ifx#2\empty\beginXMLtag\else\emptyXMLtag\fi}
+
+\def\@@traceXMLelement%
+ {\originalXMLfullidentifier
+ \ifx\originalXMLfullidentifier\currentXMLfullidentifier\else
+ \space=>\space\currentXMLfullidentifier
+ \fi
+ \ifx\currentXMLarguments\empty\else
+ \space\string|\space\currentXMLarguments
+ \fi}
+
+\long\def\traceXMLelement%
+ {\edef\originalXMLfullidentifier{\someXMLelement\currentXMLelement}%
+ \cleanupXMLarguments\writestatus{xml-element}{\@@traceXMLelement}}
+
+%D We split off the namespace part, construct the
+%D identifier, and remap the namespace if needed.
+
+\def\splitoffXMLnamespace#1:#2:#3\relax
+ {\def\rawXMLidentifier{#2}%
+ \ifx\rawXMLidentifier\empty
+ \let\currentXMLnamespace\empty
+ \edef\rawXMLidentifier{#1}%
+ \else
+ \edef\currentXMLnamespace{#1}%
+ \fi
+ \let\originalXMLnamespace\currentXMLnamespace
+ \checkXMLnamespace\rawXMLidentifier}
+
+\def\xsplitoffXMLnamespace% fast resplit
+ {\ifcsname\@@XMLnamespace:\currentXMLnamespace\endcsname
+ \csname\@@XMLnamespace:\currentXMLnamespace\endcsname
+ \fi}
+
+%D We will implement this macro later.
+
+\let\checkXMLnamespace\gobbleoneargument % see below
+
+%D The namespace attribute checking is part of the element
+%D parser, since the value of \type {xmlns} may influence other
+%D namespace mapping.
+
+\def\@@XMLns{xmlns}
+
+\def\checkXMLnamespaceattr#1% xmlns:\@@XMLname="\XMLns"
+ {\edef\XMLns{#1}%
+ \ifx\XMLns\empty \else
+ \ifcsname\@@XMLurlspace:\XMLns\endcsname
+ % get remapped namespace (from url)
+ % \edef\XMLns{\csname\@@XMLurlspace:\XMLns\endcsname}%
+ \@EA\let\@EA\XMLns\csname\@@XMLurlspace:\XMLns\endcsname
+ % remap this one
+ \ifx\@@XMLname\empty
+ % not watertight since no implicit grouping
+ \xautoXMLnamespace\XMLns
+ \else
+ \xremapXMLnamespace\@@XMLname\XMLns
+ % redo namespace remapping of self if needed
+ \ifx\XMLns\currentXMLnamespace
+ % i'm still not sure if this is ok
+ \else
+ \xsplitoffXMLnamespace
+ \fi
+ \fi
+ \fi
+ \fi}
-\long\def\defineXMLprocessor[#1]#2% watch the ?
- {\long\setvalue{\@@XMLinstruction:?#1}{#2}}
+%D Although not really needed, we clean up the arguments.
-%D As an example, we implement a \CONTEXT\ code handler:
+% \long\def\cleanupXMLarguments
+% {\ifnum\kindofXMLelement=\emptyXMLtag
+% \ifx\currentXMLarguments\empty \else
+% \@EA\docleanupXMLarguments\currentXMLarguments/\empty
+% \fi
+% \fi}
+%
+% \long\def\docleanupXMLarguments#1/#2\empty
+% {\edef\currentXMLarguments{#1}}
+%
+% we need to be ...="/" .... /> safe
-\defineXMLprocessor[context] {\contextXMLcommand}
-\defineXMLprocessor[context-command]{\contextXMLcommand}
+\long\def\cleanupXMLarguments
+ {\ifnum\kindofXMLelement=\emptyXMLtag
+ \ifx\currentXMLarguments\empty \else
+ \@EA\docleanupXMLarguments\currentXMLarguments/ \relax
+ \fi
+ \fi}
-\def\contextXMLcommand#1%
- {\pushmacro\disableXML
- \def\disableXML{\global\let\afterXMLprocessor\empty}%
- \global\let\afterXMLprocessor\enableXML
- \setnormalcatcodes\scantokens{#1}\afterXMLprocessor
- \popmacro\disableXML}
+\long\def\docleanupXMLarguments#1/ #2\relax % space added earlier
+ {\edef\currentXMLarguments{#1}}
-\defineXMLprocessor[context-directive]{\contextXMLdirective}
+\def\executeXMLelementA% no fallback
+ {\ifcsname\@@XMLelement:\currentXMLfullidentifier\endcsname
+ \csname\@@XMLelement:\currentXMLfullidentifier\endcsname
+ \fi}
-\def\contextXMLdirective#1%
- {\docontextXMLdirective#1 dummy dummy dummy\end}
+\def\executeXMLelementB% default fallback
+ {\csname \@@XMLelement:%
+ \ifcsname\@@XMLelement:\currentXMLfullidentifier\endcsname
+ \currentXMLfullidentifier
+ \else
+ \defaultXMLelement
+ \fi
+ \endcsname}
+
+\def\executeXMLelementC% no namespace of default fallback
+ {\csname \@@XMLelement:%
+ \ifcsname\@@XMLelement:\currentXMLfullidentifier\endcsname
+ \currentXMLfullidentifier
+ \else\ifcsname\@@XMLelement:\currentXMLidentifier\endcsname
+ \currentXMLidentifier
+ \else
+ \defaultXMLelement
+ \fi\fi
+ \endcsname}
+
+\def\setXMLfallbackmode#1%
+ {\ifcase#1\relax
+ \let\executeXMLelement\executeXMLelementA
+ \or
+ \let\executeXMLelement\executeXMLelementB
+ \or
+ \let\executeXMLelement\executeXMLelementC
+ \fi}
+
+\setXMLfallbackmode2
+
+%D An example of fall back modes is given below.
-\def\docontextXMLdirective#1 #2 #3 #4\end% class var value
- {\setvalue{\@@XMLvariable:#1:#2}{#3}}
+%D Later we will implement the error handler, here we handle
+%D the default case.
-\defineXMLprocessor[context-message]{\contextXMLmessage}
+\def\someXMLelement#1%
+ {\ifnum\kindofXMLelement=\endXMLtag /\fi
+ #1%
+ \ifnum\kindofXMLelement=\emptyXMLtag/\fi}
+
+\def\defaultXMLelement%
+ {\someXMLelement\s!default}
-\def\contextXMLmessage#1%
- {\writestatus{xml}{#1}}
+%D It is possible to keep track of nesting automatically,
+%D but this would kind of prohibit things like \type
+%D {\ignorespaces}. In the future we may provide an
+%D automatic depth tracking as an alternative (exclusive)
+%D mode of operation combined with space grabbing.
-\def\setnormalcatcodes%
- {\catcode`\!=\@@other \catcode`\?=\@@other
- \catcode`\&=\@@alignment \catcode`\<=\@@other
- \catcode`\#=\@@parameter \catcode`\$=\@@mathshift
- \catcode`\%=\@@comment \catcode`\\=\@@escape
- \catcode`\^=\@@superscript \catcode`\_=\@@subscript
- %\catcode`\|=\@@active \catcode`\~=\@@active
- \catcode`\{=\@@begingroup \catcode`\}=\@@endgroup}
+\def\beginXMLelement
+ {\global\advance\XMLdepth \plusone % 1
+ \global\@EA\let\csname\@@XMLdepth:\the\XMLdepth\endcsname\currentXMLelement}
-\let\disableXML\setnormalcatcodes
+\def\endXMLelement
+ {\global\advance\XMLdepth \minusone } % -1 }
-%D Given the previous definition, and given that \ETEX\ is
-%D used, we can now say:
+\def\XMLancestor#1%
+ {\ifnum\numexpr(\XMLdepth-#1)>0
+ \csname\@@XMLdepth:\the\numexpr(\XMLdepth-#1)\endcsname
+ \else
+ \currentXMLelement
+ \fi}
+
+\def\XMLparent%
+ {\XMLancestor1}
+
+% todo: split #1 into raws en reconstruct, set current etc, push and pop
+%
+% \def\beginXMLelement
+% {\dosingleempty\dobeginXMLelement}
+%
+% \def\dobeginXMLelement[#1]%
+% {\global\advance\XMLdepth 1
+% \global\@EA\let\csname\@@XMLdepth:\the\XMLdepth\endcsname\currentXMLelement
+% \global\@EA\edef\csname\@@XMLdopth:\the\XMLdepth\endcsname{\ownXMLelement}%
+% \iffirstargument\edef\ownXMLelement{#1}\fi}
+%
+% \def\endXMLelement
+% {\@EA\let\@EA\ownXMLelement\csname\@@XMLdopth:\the\XMLdepth\endcsname
+% \global\advance\XMLdepth -1 }
+
+%D \defineXMLenvironment[one]
+%D {\beginXMLelement}
+%D {\endXMLelement}
+%D
+%D \defineXMLenvironment[two]
+%D {\beginXMLelement
+%D \starttabulate
+%D \NC parent 1 \NC \XMLparent{1} \NC \NR
+%D \NC parent 2 \NC \XMLparent{2} \NC \NR
+%D \NC parent 3 \NC \XMLparent{3} \NC \NR
+%D \NC parent 4 \NC \XMLparent{4} \NC \NR
+%D \stoptabulate}
+%D {\endXMLelement}
+%D
+%D \startbuffer
+%D <x:one> <x:two> <one> <two> </two> </one> </x:two> </x:one>
+%D \stopbuffer
+%D
+%D fallback A: \setXMLfallbacklevel0 \processXMLbuffer
+%D fallback B: \setXMLfallbacklevel1 \processXMLbuffer
+%D fallback C: \setXMLfallbacklevel2 \processXMLbuffer
+
+%D Here we do the namespace (re)mapping. More examples are
+%D provided in the manual.
%D
%D \starttypen
-%D <?context {\bf Start Of Some \TeX\ Text} ?>
+%D \supportXMLnamespace [test] % needed to get a namespace working
+%D \skipXMLnamespace [test] % slow
+%D \ignoreXMLnamespace [test] % faster
+%D \defineXMLenvironment [rubish:itemize] {[} {]}
+%D \defineXMLenvironment [rubish:item] {(} {)}
+%D \remapXMLnamespace [crap] [rubish]
+%D \remapXMLnamespace [con] [context]
+%D \remapXMLurlspace [http://www.pragma-ade.com/dtd/context] [context]
+%D \autoXMLnamespace [context] % fallback
+%D \autoXMLnamespace [whatever] % second fall back
%D \stoptypen
-%D
-%D A non||\ETEX\ solution is also possible, using buffers,
-%D but for the moment we assume that \ETEX\ is used.
-%D Next we will implement the normal element handler.
+\newtoks\autoXMLnamespaces
-\let\currentXMLarguments\empty
-\let\currentXMLelement \empty
+%D The automatically mapped namespaces (the fallbacks so to
+%D day) are collected in a token list.
-\newtoks\everyXMLelement
+\let\checkedXMLnamespace\empty
-\long\def\dodoXMLelement#1 #2>%
- {\def\!!stringa{#2}%
- \def\!!stringb{/ }%
- \ifx\!!stringa\empty
- \let\currentXMLarguments\empty
- \def\currentXMLelement{#1}%
- \the\everyXMLelement
- \else\ifx\!!stringa\!!stringb
- \let\currentXMLarguments\empty
- \def\currentXMLelement{#1/}%
- \the\everyXMLelement
+\def\checkXMLnamespace#1%
+ {\edef\checkedXMLnamespace{#1}%
+ \ifcsname\@@XMLnamespace:\currentXMLnamespace\endcsname
+ \csname\@@XMLnamespace:\currentXMLnamespace\endcsname
+ % forced namespace
+ \else\ifcsname\@@XMLelement:\currentXMLelement\endcsname
+ % natural element
+ \else\ifcsname\@@XMLelement:\currentXMLelement/\endcsname
+ % natural element
\else
- \def\currentXMLelement{#1}%
- \def\currentXMLarguments{#2}%
- \the\everyXMLelement
- %\getXMLarguments\currentXMLelement{#2}%
- \dogetXMLarguments\currentXMLelement#2>%
- \fi \fi
- \executeXMLelement\currentXMLelement}
-
-\def\executeXMLelement#1%
- {\getvalue{\@@XMLelement:#1}}
-
-\newif\ifXMLrawentities
+ % locate fallback
+ \donefalse\the\autoXMLnamespaces
+ \fi\fi\fi}
-% \bgroup
-%
-% \catcode`<=\@@active
-%
-% \gdef\defineXMLentity[#1]#2%
-% {\unspaceargument#1\to\ascii
-% \long\setvalue{\@@XMLelement:ent:\@EA\firstofoneargument\ascii/}{#2}}
-%
-% \gdef\doXMLentity#1;%
-% {\ifXMLrawentities#1\else\executeXMLentity{#1}\fi}
-%
-% \gdef\executeXMLentity#1%
-% {<ent:#1/>}
-%
-% \gdef\getXMLentity#1%
-% {\getvalue{\@@XMLelement:ent:#1/}}
-%
-% \gdef\doifXMLentityelse#1#2#3%
-% {\ifundefined{\@@XMLelement:ent:#1/}#3\else#2\fi}
-%
-% \egroup
+\def\skipXMLnamespace[#1]%
+ {\letvalue{\@@XMLnamespace:#1}\doXMLskipnamespace}
-\gdef\defineXMLentity[#1]#2%
- {\unspaceargument#1\to\ascii
- \long\setvalue{\@@XMLentity:\@EA\firstofoneargument\ascii}{#2}}
+\def\doXMLskipnamespace
+ {\long\@EA\def\csname\@@XMLelement:\checkedXMLnamespace\endcsname
+ {\getXMLgroupedignore\checkedXMLnamespace}}
+
+\def\hideXMLnamespace[#1]%
+ {\letvalue{\@@XMLnamespace:#1}\doXMLhidenamespace}
+
+\def\doXMLhidenamespace
+ {\long\@EA\def\csname\@@XMLelement:\checkedXMLnamespace\endcsname
+ {\redoXMLignore\checkedXMLnamespace}}
+
+\def\ignoreXMLnamespace[#1]%
+ {\letvalue{\@@XMLnamespace:#1}\doXMLignorenamespace}
+
+\def\doXMLignorenamespace % \let binnen def
+ {\long\@EA\def\csname\@@XMLelement:\checkedXMLnamespace\endcsname
+ {\@EA\redoXMLignore\@EA{\checkedXMLnamespace}}} % EA ?
+
+\def\remapXMLnamespace
+ {\dodoubleargument\doremapXMLnamespace}
+
+\def\doremapXMLnamespace[#1][#2]%
+ {\ifsecondargument
+ \setvalue{\@@XMLnamespace:#1}{\def\currentXMLnamespace{#2}}%
+ \else
+ \letvalue{\@@XMLnamespace:#1}\relax
+ \fi}
+
+\def\supportXMLnamespace%
+ {\dosingleargument\dosupportXMLnamespace}
+
+\def\dosupportXMLnamespace[#1]%
+ {\setvalue{\@@XMLnamespace:#1}{\def\currentXMLnamespace{#1}}}
+
+\def\xremapXMLnamespace#1#2% fast internal one
+ {\@EA\edef\csname\@@XMLnamespace:#1\endcsname
+ {\def\noexpand\currentXMLnamespace{#2}}}
+
+\def\autoXMLnamespace[#1]%
+ {\xautoXMLnamespace{#1}}
+
+\def\xautoXMLnamespace#1% fast internal one
+ {\ifcsname\@@XMLnamespace-#1\endcsname\else
+ \@EA\appendtoks\csname\@@XMLnamespace-#1\endcsname\to\autoXMLnamespaces
+ \fi
+ \@EA\edef\csname\@@XMLnamespace-#1\endcsname
+ {\noexpand\doautoXMLnamespace{#1}}}
+
+\def\doautoXMLnamespace#1% \done is set before list
+ {\ifdone\else
+ \ifcsname\@@XMLelement:#1:\checkedXMLnamespace\endcsname
+ \def\currentXMLnamespace{#1}%
+ \else\ifcsname\@@XMLelement:#1:\checkedXMLnamespace/\endcsname
+ \def\currentXMLnamespace{#1}%
+ \fi\fi
+ \fi}
+
+\def\resetXMLnamespace[#1]%
+ {\letvalue{\@@XMLnamespace-#1}\gobbleoneargument
+ \letvalue{\@@XMLnamespace:#1}\gobbleoneargument}
+
+\def\remapXMLurlspace
+ {\dodoubleargument\doremapXMLurlspace}
-% we need to be able to do:
+\def\doremapXMLurlspace[#1][#2]%
+ {\setvalue{\@@XMLurlspace:#1}{#2}}
+
+%D Entities needs a bit more work, as well as a connection
+%D with the encoding handlers.
+
+% we need to be able to do:
%
% \defineXMLentity[amp] {\FunnyAmp} \def\FunnyAmp#1;{\getXMLentity{#1}}
%
% \defineXMLentity [pound] {(why not use euro's?)}
-%
+%
% \startXMLdata
% test &amp;pound; test
% \stopXMLdata
%
-% so we need an ifless implementation of:
+% so we need an ifless implementation
-\gdef\doXMLentity#1;%
- {\ifXMLrawentities
- \expandafter\firstofoneargument
+% \eacute -> simplified -> e (via raw encoding)
+% -> raw -> eacute (via handler)
+%
+% naming sucks
+
+\newif\ifXMLrawentities % proper fallback
+\newif\ifXMLsimpleentities % last resort
+
+\def\simpleXMLencoding{raw}
+
+\def\simplifyXMLentities%
+ {\fastenableencoding\simpleXMLencoding
+ \XMLsimpleentitiestrue}
+
+\gdef\defineXMLentity%
+ {\dodoubleempty\dodefineXMLentity}
+
+\gdef\dodefineXMLentity[#1][#2]#3%
+ {\ifsecondargument
+ \defineXMLentities[#1]{#2}{#3}%
+ \else
+ \dododefineXMLentity{#1}{#3}%
+ \fi}
+
+\def\defineXMLentities[#1]#2#3%
+ {\dododefineXMLentity{#1}{\ifXMLsimpleentities#2\else#3\fi}}
+
+\gdef\dododefineXMLentity#1#2%
+ {\unspaceargument#1\to\ascii % #1 can be {[} or so
+ \long\setvalue{\@@XMLentity:\@EA\firstofoneargument\ascii}{#2}}
+
+%D May this wile become dodo (more in tune with rest);
+%D beware: also remapped in xtag-map.
+
+\gdef\doXMLentity#1#2;% interesting: # is now ##
+ {\if\string#1\letterhash
+ \@EA\parseXMLcharacter
+ \else\ifXMLrawentities
+ \@EAEAEA\firstofoneargument
+ \else
+ \@EAEAEA\executeXMLentity
+ \fi\fi{#1#2}}
+
+%D Here we need to get rid of the double hash and act upon the
+%D number. Proper hex/oct number support can be implemented by
+%D redefining \type {\executeXMLcharacter}.
+
+% \def\parseXMLcharacter#1% gobble the ##x
+% {\@EA\executeXMLcharacter\@EA{\gobblethreearguments#1}}
+%
+% single hash now
+%
+% \def\parseXMLcharacter#1%
+% {\@EA\executeXMLcharacter\@EA{\gobbleoneargument#1}}
+%
+% \def\executeXMLcharacter#1% can be overloaded
+% {\ifnum"#1<256
+% \@EA\getXMLcharacter
+% \else\ifXMLrawentities
+% \@EAEAEA\firstofoneargument
+% \else
+% \@EAEAEA\unknownXMLcharacter
+% \fi\fi{\number"#1}}
+%
+% \unexpanded\def\getXMLcharacter#1{\rawcharacter{#1}}
+
+\def\parseXMLcharacter#1%
+ {\@EA\executeXMLcharacter\gobbleoneargument#1\empty\relax}
+
+\def\executeXMLcharacter#1#2\relax
+ {\if#1x%
+ \@EA\executeXMLhexcharacter
+ \else
+ \@EA\executeXMLdeccharacter
+ \fi#1#2\relax}
+
+% \def\executeXMLhexcharacter x#1\relax % can be overloaded
+% {\ifnum"#1<256
+% \@EA\getXMLcharacter
+% \else\ifXMLrawentities
+% \@EAEAEA\firstofoneargument
+% \else
+% \@EAEAEA\unknownXMLcharacter
+% \fi\fi{\number"#1}}
+
+\def\executeXMLhexcharacter x#1\relax % can be overloaded
+ {\uppercase{\doexecuteXMLhexcharacter#1\relax}}
+
+\def\doexecuteXMLhexcharacter#1\relax
+ {\ifnum"#1<256
+ \@EA\getXMLcharacter
+ \else\ifXMLrawentities
+ \@EAEAEA\firstofoneargument
+ \else
+ \@EAEAEA\unknownXMLcharacter
+ \fi\fi{\number"#1}}
+
+% ==
+%
+% \def\executeXMLhexcharacter x#1\relax
+% {\uppercase{\ifnum"#1}<256
+% \@EA\getXMLcharacter
+% \else\ifXMLrawentities
+% \@EAEAEA\firstofoneargument
+% \else
+% \@EAEAEA\unknownXMLcharacter
+% \fi\fi{\uppercase{\number"#1}}}
+
+\def\executeXMLdeccharacter#1\relax % can be overloaded
+ {\ifnum#1<256
+ \@EA\getXMLcharacter
+ \else\ifXMLrawentities
+ \@EAEAEA\firstofoneargument
+ \else
+ \@EAEAEA\unknownXMLcharacter
+ \fi\fi{\number#1}}
+
+\unexpanded\def\getXMLcharacter#1%
+ {\ifcsname\@@XMLentity:#1\endcsname
+ \@EA\getXMLentity
\else
- \expandafter\executeXMLentity
+ \@EA\rawcharacter
\fi{#1}}
-\def\executeXMLentity#1% internal ! ! !
+\def\unknownXMLcharacter#1{[#1]}
+
+% \useXMLfilter[ent]
+%
+% \defineXMLsingular[test]{{\simplifyXMLentities\XMLpar{test}{bla}{}}}
+%
+% \startXMLdata
+% <test bla="&#xD3;bla&eacute;bla&tex;and$and&#xFC;ziezo&#xF99;" />
+% \stopXMLdata
+%
+% \defineXMLentity[45]{|it works|} % {|-|}
+%
+% \startXMLdata
+% text&#045;&#046;text
+% text&#x045;&#x046;text
+% \stopXMLdata
+
+%D May be this will change a bit ...
+
+\def\executeXMLentity#1% named one
{\getXMLentity{#1}}
-\def\expandedXMLentity#1%
- {\getvalue{\@@XMLentity:#1}}
+%\def\expandedXMLentity#1%
+% {\ifcsname\@@XMLentity:#1\endcsname\csname\@@XMLentity:#1\endcsname\fi}
+%
+%\unexpanded\def\getXMLentity#1%
+% {\ifcsname\@@XMLentity:#1\endcsname\csname\@@XMLentity:#1\endcsname\fi}
+%
+%\def\expandedXMLentity#1%
+% {\csname\@@XMLentity:#1\endcsname}
+%
+%\unexpanded\def\getXMLentity#1%
+% {\csname\@@XMLentity:#1\endcsname}
+
+\newif\ifautoXMLentities % fall back on context commands
+
+\def\expandedXMLentity#1%
+ {\ifcsname\@@XMLentity:#1\endcsname \@EA \execXMLentity
+ \else\ifautoXMLentities \@EAEAEA \autoXMLentity
+ \else \@EAEAEA \crapXMLentity
+ \fi\fi{#1}}
+
+\def\execXMLentity#1%
+ {\csname\@@XMLentity:#1\endcsname}
+
+\def\crapXMLentity#1%
+ {\inframed[\c!offset=.1ex]{\tttf#1}}
+
+\def\autoXMLentity#1%
+ {\ifcsname#1\endcsname\csname#1\endcsname\fi}
-\unexpanded\def\getXMLentity#1%
- {\getvalue{\@@XMLentity:#1}}
+\unexpanded\def\getXMLentity{\expandedXMLentity}
\gdef\doifXMLentityelse#1#2#3%
- {\ifundefined{\@@XMLentity:#1}#3\else#2\fi}
+ {\ifcsname\@@XMLentity:#1\endcsname#2\else#3\fi}
-% \long\def\getXMLarguments#1#2%
-% {\dogetXMLarguments{#1}#2>}
-%
-% \long\def\dogetXMLarguments#1%
-% {\XMLtoks\emptytoks
-% \def\@@XMLclass{#1}%
-% \let\dodoparseXMLarguments\doparseXMLarguments
-% \doparseXMLarguments}
-%
-% \def\dosetXMLargument#1%
-% {\setvalue{\@@XMLvariable:\@@XMLclass:\@@XMLname}{#1}%
-% %\message{[\@@XMLname=#1]}%
-% \let\dodoparseXMLarguments\doparseXMLarguments
-% \dodoparseXMLarguments}
-
-% see \defineXML... commands:
+% see \defineXML... commands:
%
% [key=val] => \presetXMLarguments{element} => default key/vals
% [blabla] => \theXMLarguments{blabla} => user key/vals
@@ -496,78 +1039,217 @@
%
% <element key="val"> stored in case of [blabla] else set as \XMLpar
%
-% see m-steps for an example of usage
+% see m-steps for an example of usage
+
+\let\@@XMLmapmap\empty
+\newif\ifXMLnamespace
\long\def\getXMLarguments#1#2%
- {\dogetXMLarguments{#1}#2>}
+ {\XMLnamespacefalse
+ \dogetXMLarguments{#1}#2>}
+
+\let\dosetXMLattributeA\gobbleoneargument
+
+\def\dosetXMLattributeB#1%
+ {\ifx\@@XMLspac\originalXMLnamespace
+ \@EA\def\csname\@@XMLvariable:\@@XMLclass:\@@XMLname\endcsname{#1}%
+ \fi}
+
+% \def\dosetXMLattributeC#1%
+% {\ifx\@@XMLspac\originalXMLnamespace
+% \@EA\def\csname\@@XMLvariable:\@@XMLclass:\@@XMLname\endcsname{#1}%
+% \else
+% \@EA\def\csname\@@XMLvariable:\@@XMLclass:\@@XMLspac:\@@XMLname\endcsname{#1}%
+% \fi}
+
+\def\dosetXMLattributeC%
+ {\@EA\def\csname\@@XMLvariable:\@@XMLclass\ifx\@@XMLspac
+ \originalXMLnamespace\else:\@@XMLspac\fi:\@@XMLname\endcsname}
+
+% \def\dosetXMLattributeD#1%
+% {\ifx\@@XMLspac\originalXMLnamespace
+% \@EA\def\csname\@@XMLvariable:\@@XMLclass:\currentXMLnamespace:\@@XMLname\endcsname{#1}%
+% \else
+% \@EA\def\csname\@@XMLvariable:\@@XMLclass:\@@XMLspac:\@@XMLname\endcsname{#1}%
+% \fi}
+
+\def\dosetXMLattributeD%
+ {\@EA\def\csname\@@XMLvariable:\@@XMLclass:\ifx\@@XMLspac
+ \originalXMLnamespace\currentXMLnamespace\else\@@XMLspac\fi
+ :\@@XMLname\endcsname}
+
+\def\setXMLattributemode#1%
+ {\ifcase#1\relax
+ \let\dosetXMLattribute\dosetXMLattributeA
+ \or
+ \let\dosetXMLattribute\dosetXMLattributeB
+ \or
+ \let\dosetXMLattribute\dosetXMLattributeC
+ \or
+ \let\dosetXMLattribute\dosetXMLattributeD
+ \fi}
+
+\setXMLattributemode{2} % a reasonable default
+
+\let\@@XMLspac\empty % argumentnamespace
\long\def\dogetXMLarguments#1%
{\XMLtoks\emptytoks
\ifcsname\@@XMLmap:#1\endcsname
- \let\dosetXMLargument\dosetXMLargumentB
+ \let\dodosetXMLargument\dodosetXMLargumentB
\else
\def\@@XMLclass{#1}%
- \let\dosetXMLargument\dosetXMLargumentA
+ \let\dodosetXMLargument\dodosetXMLargumentA
\fi
\let\dodoparseXMLarguments\doparseXMLarguments
\doparseXMLarguments}
-\def\dosetXMLargumentA#1%
- {\setvalue{\@@XMLvariable:\@@XMLclass:\@@XMLname}{#1}%
+\long\def\doparseXMLarguments#1% space goes ok
+ {\if#1>%
+ \let\dodoparseXMLarguments\empty
+ \else\if#1=%
+ \edef\@@XMLname{\the\XMLtoks}%
+ \XMLtoks\emptytoks
+ \else\if#1"%
+ \let\dodoparseXMLarguments\dodoparseXMLargumentsD
+ \else\if#1'%
+ \let\dodoparseXMLarguments\dodoparseXMLargumentsS
+ \else\if#1:%
+ \XMLnamespacetrue
+ \edef\@@XMLspac{\the\XMLtoks}%
+ \XMLtoks\emptytoks
+ \else\if#1/%
+ \chardef\kindofXMLelement\emptyXMLtag
+ \else
+ \XMLtoks\@EA{\the\XMLtoks#1}%
+ \fi\fi\fi\fi\fi\fi
+ \dodoparseXMLarguments}
+
+\def\dodoparseXMLargumentsD#1"{\dosetXMLargument{#1}}
+\def\dodoparseXMLargumentsS#1'{\dosetXMLargument{#1}}
+
+\def\dosetXMLargument#1%
+ {\ifXMLnamespace
+ \ifx\@@XMLspac\@@XMLns
+ \checkXMLnamespaceattr{#1}% xmlns:\@@XMLname="#1"
+ \else
+ \dosetXMLattribute{#1}% some:\@@XMLname="#1"
+ \fi
+ \XMLnamespacefalse
+ \else\ifx\@@XMLname\@@XMLns
+ \checkXMLnamespaceattr{#1}% xmlns="#1"
+ \else
+ \dodosetXMLargument{#1}%
+ \fi\fi
\let\dodoparseXMLarguments\doparseXMLarguments
- %\message{[\@@XMLclass][\@@XMLname=#1]}\wait
\dodoparseXMLarguments}
-\def\dosetXMLargumentB#1%
- {\setevalue{\@@XMLmap:\@@XMLmapmap}%
- {\@EA\ifx\csname\@@XMLmap:\@@XMLmapmap\endcsname\empty\else
- \csname\@@XMLmap:\@@XMLmapmap\endcsname,%
- \fi
- \@@XMLname=#1}%
+\def\dosetXMLargument#1% ugly alternative
+ {\ifXMLnamespace
+ \XMLnamespacefalse
+ \ifx\@@XMLspac\@@XMLns
+ \@EAEAEA\checkXMLnamespaceattr % xmlns:\@@XMLname="#1"
+ \else
+ \@EAEAEA\dosetXMLattribute % some:\@@XMLname="#1"
+ \fi
+ \else\ifx\@@XMLname\@@XMLns
+ \@EAEAEA\checkXMLnamespaceattr % xmlns="#1"
+ \else
+ \@EAEAEA\dodosetXMLargument
+ \fi\fi{#1}%
\let\dodoparseXMLarguments\doparseXMLarguments
- %\message{[\@@XMLprefix][\@@XMLname=#1]}\wait
\dodoparseXMLarguments}
+\def\dodosetXMLargumentA%
+ {\@EA\def\csname\@@XMLvariable:\@@XMLclass:\@@XMLname\endcsname}
+
+\def\dodosetXMLargumentB#1%
+ {\@EA\edef\csname\@@XMLmap:\@@XMLmapmap\endcsname
+ {\@EA\ifx\csname\@@XMLmap:\@@XMLmapmap\endcsname\empty\else
+ \csname\@@XMLmap:\@@XMLmapmap\endcsname,%
+ \fi
+ \@@XMLname=#1}}
+
\appendtoks
- \resetXMLarguments\currentXMLelement
+ \resetXMLarguments{\rawXMLnamespace\rawXMLidentifier}%
\to \everyXMLelement
\def\resetXMLarguments#1%
{\ifcsname\@@XMLmap:#1\endcsname
- \@EA\let\@EA\@@XMLmapmap\csname\@@XMLmap:#1\endcsname
- \@EA\let\csname\@@XMLmap:\@@XMLmapmap\endcsname\empty
- \fi}
+ \@EA\let\@EA\@@XMLmapmap\csname\@@XMLmap:#1\endcsname
+ \@EA\let\csname\@@XMLmap:\@@XMLmapmap\endcsname\empty
+ \fi}
\def\theXMLarguments#1%
{\ifcsname\@@XMLmap:#1\endcsname\csname\@@XMLmap:#1\endcsname\fi}
-\long\def\doparseXMLarguments#1% space goes ok
- {\if#1>%
- \let\dodoparseXMLarguments\empty
- \else\if#1=%
- \edef\@@XMLname{\the\XMLtoks}%
- \XMLtoks\emptytoks
- \else\if#1"%
- \let\dodoparseXMLarguments\dodoparseXMLargumentsD
- \else\if#1'%
- \let\dodoparseXMLarguments\dodoparseXMLargumentsS
- \else\if#1/%
- \edef\currentXMLelement{\currentXMLelement/}%
- \else
- \@EA\XMLtoks\@EA{\the\XMLtoks#1}%
- \fi\fi\fi\fi\fi
- \dodoparseXMLarguments}
+\newtoks\globalscratchtoks
+
+\def\expandXMLvalue#1%
+ {\ifcsname#1\endcsname
+ \bgroup
+\enableXMLexpansion
+ \let\getXMLentity\expandedXMLentity
+ \expanded{\global\globalscratchtoks{\csname#1\endcsname}}%
+ \egroup
+ \@EA\edef\csname#1\endcsname{\the\globalscratchtoks}%
+ \fi}
+
+\def\expandTEXpar #1#2{\expandXMLvalue{#1\interfaced{#2}}}
+\def\expandXMLpar #1#2{\expandXMLvalue{\@@XMLvariable:#1:#2}}
+\def\expandXMLarguments#1{\expandXMLvalue{\@@XMLmap:#1}}
+
+%D \startbuffer[tex]
+%D \defineXMLsingular [fx:root]
+%D {\XMLNSpar{fx:root}{xml}{lang}{}
+%D \XMLpar{fx:root}{xml:lang}{}
+%D \starttabulate[||||]
+%D \HL
+%D \NC \bf mode \NC \bf call \NC \bf result \NC\NR
+%D \HL
+%D \NC 0\NC\asciistr{\XMLpar {fx:root} {crap} {}} \NC dirt \NC\NR
+%D \NC \NC\asciistr{\XMLpar {fx:root} {junk} {}} \NC \NC\NR
+%D \NC \NC\asciistr{\XMLNSpar {fx:root} {fx} {crap} {}}\NC \NC\NR
+%D \NC \NC\asciistr{\XMLNSpar {fx:root} {xml} {lang} {}}\NC \NC\NR
+%D \HL
+%D \NC 1\NC\asciistr{\XMLpar {fx:root} {crap} {}} \NC dirt \NC\NR
+%D \NC \NC\asciistr{\XMLpar {fx:root} {junk} {}} \NC junk \NC\NR
+%D \NC \NC\asciistr{\XMLNSpar {fx:root} {fx} {crap} {}}\NC \NC\NR
+%D \NC \NC\asciistr{\XMLNSpar {fx:root} {xml} {lang} {}}\NC \NC\NR
+%D \HL
+%D \NC 2\NC\asciistr{\XMLpar {fx:root} {crap} {}} \NC dirt \NC\NR
+%D \NC \NC\asciistr{\XMLpar {fx:root} {junk} {}} \NC junk \NC\NR
+%D \NC \NC\asciistr{\XMLNSpar {fx:root} {fx} {crap} {}}\NC \NC\NR
+%D \NC \NC\asciistr{\XMLNSpar {fx:root} {xml} {lang} {}}\NC en \NC\NR
+%D \HL
+%D \NC 3\NC\asciistr{\XMLpar {fx:root} {crap} {}} \NC dirt \NC\NR
+%D \NC \NC\asciistr{\XMLpar {fx:root} {junk} {}} \NC junk \NC\NR
+%D \NC \NC\asciistr{\XMLNSpar {fx:root} {fx} {crap} {}}\NC rubish\NC\NR
+%D \NC \NC\asciistr{\XMLNSpar {fx:root} {xml} {lang} {}}\NC en \NC\NR
+%D \HL
+%D \stoptabulate}
+%D
+%D \remapXMLurlspace [http://www.w3.org/1999/XSL/Format] [fx]
+%D \stopbuffer
+%D
+%D \startbuffer[xml]
+%D <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
+%D fo:crap="rubish"
+%D fo:junk="junk"
+%D xml:lang="en"
+%D crap="dirt" />
+%D \stopbuffer
+%D
+%D \typebuffer[tex] \processTEXbuffer[tex]
+%D \typebuffer[xml] \processXMLbuffer[xml]
-\def\dodoparseXMLargumentsD#1"{\dosetXMLargument{#1}}
-\def\dodoparseXMLargumentsS#1'{\dosetXMLargument{#1}}
-
%D The previous macros were the basic parser and their working
%D is left to the imagination of the reader. These macros
-%D will be improved.
+%D will be improved over time. We use rather low level
+%D definitions so that the mappings will run as fast as
+%D possible.
-\bgroup
-
-\catcode`<=\@@active
+\bgroup \catcode`<=\@@active
\long\gdef\dododefineXMLsingular#1#2%
{\long\setvalue{\@@XMLelement:#1/}{#2}}
@@ -580,30 +1262,76 @@
{\long\setvalue{\@@XMLelement:#1}{\groupedcommand{#2}{}\bgroup}%
\long\setvalue{\@@XMLelement:/#1}{\egroup}}
+%\long\gdef\dododefineXMLargument#1#2% watch the {} around ##1
+% {\long\setvalue{\@@XMLelement:#1/}{#2{}}%
+% \long\setvalue{\@@XMLelement:#1}##1</#1>{#2{##1}}}
+
\long\gdef\dododefineXMLargument#1#2% watch the {} around ##1
{\long\setvalue{\@@XMLelement:#1/}{#2{}}%
- \long\setvalue{\@@XMLelement:#1}##1</#1>{#2{##1}}}
+ \long\setvalue{\@@XMLelement:#1}{\redoXMLargument{#1}{#2}}}
+
+\long\gdef\redoXMLargument#1#2%
+ {\long\@EA\def\@EA\next\@EA##\@EA1\@EA<\@EA/\currentXMLelement>{#2{##1}}%
+ \next}
+
+%\long\gdef\dododefineXMLignore#1%
+% {\long\setvalue{\@@XMLelement:#1/}{}%
+% \long\setvalue{\@@XMLelement:#1}##1</#1>{}}
\long\gdef\dododefineXMLignore#1%
{\long\setvalue{\@@XMLelement:#1/}{}%
- \long\setvalue{\@@XMLelement:#1}##1</#1>{}}
+ \long\setvalue{\@@XMLelement:#1}{\redoXMLignore{#1}}}
+
+\long\gdef\redoXMLignore#1%
+ {\long\@EA\def\@EA\next\@EA##\@EA1\@EA<\@EA/\currentXMLelement>{}%
+ \next}
+
+%\long\gdef\dododefineXMLpickup#1#2#3%
+% {\long\setvalue{\@@XMLelement:#1/}{#2#3}%
+% \long\setvalue{\@@XMLelement:#1}##1</#1>{#2##1#3}}
\long\gdef\dododefineXMLpickup#1#2#3%
{\long\setvalue{\@@XMLelement:#1/}{#2#3}%
- \long\setvalue{\@@XMLelement:#1}##1</#1>{#2##1#3}}
+ \long\setvalue{\@@XMLelement:#1}{\redoXMLpickup{#1}{#2}{#3}}}
+
+\long\gdef\redoXMLpickup#1#2#3%
+ {\long\@EA\def\@EA\next\@EA##\@EA1\@EA<\@EA/\currentXMLelement>{#2##1#3}%
+ \next}
\long\gdef\dododefineXMLenvironment#1#2#3%
- {\long\setvalue{\@@XMLelement:#1/}{#2#3}% % genereert evt relax
+ {\long\setvalue{\@@XMLelement:#1/}{#2#3}%
\long\setvalue{\@@XMLelement:#1}{#2}%
\long\setvalue{\@@XMLelement:/#1}{#3}}
-\long\gdef\dododefineXMLpush#1%
- {\long\setvalue{\@@XMLelement:#1/}{\long\setvalue{\@@XMLdata:#1}{}}%
- \long\setvalue{\@@XMLelement:#1}##1</#1>{\long\setvalue{\@@XMLdata:#1}{##1}}}
+%\long\gdef\dododefineXMLsave#1%
+% {\letvalue{\@@XMLdata:#1}\longempty
+% \long\setvalue{\@@XMLelement:#1/}{\long\setvalue{\@@XMLdata:#1}{}}%
+% \long\setvalue{\@@XMLelement:#1}##1</#1>{\long\setvalue{\@@XMLdata:#1}{##1}}}
-\long\gdef\dododefineXMLenvironmentpush#1#2#3%
- {\long\setvalue{\@@XMLelement:#1/}{#2\long\setvalue{\@@XMLdata:#1}{}#3}%
- \long\setvalue{\@@XMLelement:#1}##1</#1>{#2\long\setvalue{\@@XMLdata:#1}{##1}#3}}
+\long\gdef\dododefineXMLsave#1%
+ {\letvalue{\@@XMLdata:#1}\longempty
+ \long\setvalue{\@@XMLelement:#1/}{\long\setvalue{\@@XMLdata:#1}{}}%
+ \long\setvalue{\@@XMLelement:#1}{\redoXMLsave{#1}}}
+
+\gdef\redoXMLsave#1%
+ {\long\@EA\def\@EA\next\@EA##\@EA1\@EA<\@EA/\currentXMLelement>%
+ {\long\@EA\def\csname\@@XMLdata:#1\endcsname{##1}}%
+ \next}
+
+%\long\gdef\dododefineXMLenvironmentsave#1#2#3%
+% {\letvalue{\@@XMLdata:#1}\longempty
+% \long\setvalue{\@@XMLelement:#1/}{#2\long\setvalue{\@@XMLdata:#1}{}#3}%
+% \long\setvalue{\@@XMLelement:#1}##1</#1>{#2\long\setvalue{\@@XMLdata:#1}{##1}#3}}
+
+\long\gdef\dododefineXMLenvironmentsave#1#2#3%
+ {\letvalue{\@@XMLdata:#1}\longempty
+ \long\setvalue{\@@XMLelement:#1/}{#2\long\setvalue{\@@XMLdata:#1}{}#3}%
+ \long\setvalue{\@@XMLelement:#1}{\redoXMLenvironmentsave{#1}{#2}{#3}}}
+
+\gdef\redoXMLenvironmentsave#1#2#3%
+ {\long\@EA\def\@EA\next\@EA##\@EA1\@EA<\@EA/\currentXMLelement>%
+ {#2\long\@EA\def\csname\@@XMLdata:#1\endcsname{##1}#3}%
+ \next}
\long\gdef\dododefineXMLprocess#1%
{\long\setvalue{\@@XMLelement:#1/}{}%
@@ -627,11 +1355,16 @@
\def\defineXMLignore {\dotripleempty\dodefineXMLignore}
\def\defineXMLpickup {\dotripleempty\dodefineXMLpickup}
\def\defineXMLenvironment {\dotripleempty\dodefineXMLenvironment}
-\def\defineXMLpush {\dotripleempty\dodefineXMLpush}
-\def\defineXMLenvironmentpush{\dotripleempty\dodefineXMLenvironmentpush}
+\def\defineXMLsave {\dotripleempty\dodefineXMLsave}
+\def\defineXMLenvironmentsave{\dotripleempty\dodefineXMLenvironmentsave}
\def\defineXMLprocess {\dotripleempty\dodefineXMLprocess}
-% goes for all types
+% push is (not yet) a real push, so:
+
+\def\defineXMLpush {\dotripleempty\dodefineXMLsave}
+\def\defineXMLenvironmentpush{\dotripleempty\dodefineXMLenvironmentsave}
+
+% goes for all types
\def\defineXMLnested {\dotripleempty\dodefineXMLnestedenvironment}
\def\defineXMLnestedenvironment{\dotripleempty\dodefineXMLnestedenvironment}
@@ -658,11 +1391,11 @@
\long\def\dodefineXMLenvironment[#1][#2][#3]#4#5%
{\defineXMLmethod\dododefineXMLenvironment{#1}{#2}{#3}{#4}{#5}}
-\long\def\dodefineXMLpush[#1][#2][#3]%
- {\defineXMLmethod\dododefineXMLpush{#1}{#2}{#3}{}{}}
+\long\def\dodefineXMLsave[#1][#2][#3]%
+ {\defineXMLmethod\dododefineXMLsave{#1}{#2}{#3}{}{}}
-\long\def\dodefineXMLenvironmentpush[#1][#2][#3]#4#5%
- {\defineXMLmethod\dododefineXMLenvironmentpush{#1}{#2}{#3}{#4}{#5}}
+\long\def\dodefineXMLenvironmentsave[#1][#2][#3]#4#5%
+ {\defineXMLmethod\dododefineXMLenvironmentsave{#1}{#2}{#3}{#4}{#5}}
\long\def\dodefineXMLprocess[#1][#2][#3]%
{\defineXMLmethod\dododefineXMLprocess{#1}{#2}{#3}{}{}}
@@ -678,105 +1411,151 @@
% [blabla] [key=val] => \presetXMLarguments{element} => default key/vals
% \theXMLarguments{blabla} => user key/vals
-\long\def\defineXMLmethod#1#2#3#4#5#6% command element [map] [parlst] begin end
+% command element [map] [parlst] begin end
+
+\long\def\defineXMLmethod#1#2#3#4#5#6%
{\ifsecondargument
- \setXMLarguments{#2}{#3}{#4}%
- \fi
- \ifignoreXMLcase
- \lowercasestring#2\to\ascii \@EA#1\@EA{\ascii}{#5}{#6}%
- \uppercasestring#2\to\ascii \@EA#1\@EA{\ascii}{#5}{#6}%
+ \setXMLarguments{#2}{#3}{#4}%
\else
- #1{#2}{#5}{#6}%
- \fi}
+ \resetXMLarguments{#2}% new
+ \fi
+ #1{#2}{#5}{#6}}
+
+%D Arguments (attributes) \unknown
-\def\setXMLarguments#1#2#3% element [tag] settings
+\long\def\setXMLarguments#1#2#3% element [tag] settings
{\doifassignmentelse{#2}
- {\setvalue{\@@XMLpars:#1}{\getrawparameters[\@@XMLvariable:#1:][#2]}}
- {\setvalue{\@@XMLmap :#1}{#2}% later we can init vars by this name
- \doifsomething{#3}{\setvalue{\@@XMLpars:#1}{\getrawparameters[#2][#3]}}}}
+ {\long\setvalue{\@@XMLpars:#1}{\getrawparameters[\@@XMLvariable:#1:][#2]}}
+ {\long\setvalue{\@@XMLmap :#1}{#2}% later we can init vars by this name
+ \doifsomething{#3}{\long\setvalue{\@@XMLpars:#1}{\getrawparameters[#2][#3]}}}}
\def\presetXMLarguments#1%
- {\getvalue{\@@XMLpars:#1}}
+ {\csname\@@XMLpars:\rawXMLnamespace#1\endcsname} % == \getvalue{}
\prependtoks
- \presetXMLarguments\currentXMLelement
+ \presetXMLarguments\rawXMLidentifier
\to \everyXMLelement
-\def\doifXMLdataelse#1#2#3% % \relax too, so no etex
-% wrong
-% {\expandafter\ifx\csname\@@XMLdata:#1\endcsname\relax
-% slow
-% {\ifundefined{\@@XMLdata:#1}%
-% etex
- {\unless\ifcsname\@@XMLdata:#1\endcsname
- #3%
- \else\expandafter\ifx\csname\@@XMLdata:#1\endcsname\empty
- #3%
- \else\expandafter\ifx\csname\@@XMLdata:#1\endcsname\relax
- #3%
+\long\def\longempty{}
+\long\def\longspace{ }
+
+\def\doifelseXMLdata#1% always empty at start [gets a long assignment]
+ {\@EA\ifx\csname\@@XMLdata:#1\endcsname\longempty
+ \expandafter\secondoftwoarguments
\else
- #2%
- \fi\fi\fi}
+ \expandafter\firstoftwoarguments
+ \fi}
-\def\XMLpop#1% one level
-% wrong
-% {\expandafter\ifx\csname\@@XMLdata:#1\endcsname\relax\else
-% \csname\@@XMLdata:#1\endcsname
-% \fi}
-% slow, hm was not commented
-% {\ifundefined{\@@XMLdata:#1}\else\getvalue{\@@XMLdata:#1}\fi}
-% etex
- {\ifcsname\@@XMLdata:#1\endcsname\csname\@@XMLdata:#1\endcsname\fi}
-
-\def\XMLpopdata#1% see m-steps for usage
- {\unless\ifcsname\@@XMLdata:#1\endcsname
- \else\expandafter\ifx\csname\@@XMLdata:#1\endcsname\empty
- \else\expandafter\ifx\csname\@@XMLdata:#1\endcsname\relax
+\def\doifXMLdata#1% always empty at start [gets a long assignment]
+ {\@EA\ifx\csname\@@XMLdata:#1\endcsname\longempty
+ \expandafter\gobbleoneargument
\else
- \@EA\@EA\@EA\XMLdata\@EA\@EA\@EA{\csname\@@XMLdata:#1\endcsname}%
- \fi\fi\fi}
+ \expandafter\firstofoneargument
+ \fi}
+
+\let\doifXMLdataelse\doifelseXMLdata
+
+\def\doifelseXMLempty#1%
+ {\@EA\ifx\csname\@@XMLdata:#1\endcsname\longempty
+ \expandafter\firstoftwoarguments
+ \else\@EA\ifx\csname\@@XMLdata:#1\endcsname\longspace
+ \expandthree\firstoftwoarguments
+ \else
+ \expandthree\secondoftwoarguments
+ \fi\fi}
-\def\XMLappend#1#2%
- {\edef\!!stringa{\@@XMLdata:#1}%
- \doifXMLdataelse{#1}%
- {\@EA\@EA\@EA\setvalue\@EA\@EA\@EA\!!stringa\@EA\@EA\@EA
- {\csname\!!stringa\endcsname#2}}
- {\setvalue\!!stringa{#2}}}
+% test case:
+%
+% \defineXMLenvironmentsave[test]
+% {}
+% {\message{[\XMLflush{test}]}
+% \message{\doifelseXMLdata {test}{}{no }data}
+% \message{/}
+% \message{\doifelseXMLempty{test}{}{not }empty}
+% \wait}
+%
+% \startXMLdata
+% <test>xxx</test>
+% <test></test>
+% <test> </test>
+% <test> </test>
+% <test> </test>
+% <test> x </test>
+% \stopXMLdata
+
+\def\XMLflush#1% one level
+ {\csname\@@XMLdata:#1\endcsname}
+
+\def\XMLflushdata#1% see m-steps for usage
+ {\@EA\ifx\csname\@@XMLdata:#1\endcsname\longempty\else
+ \@EAEAEA\XMLdata\@EA\@EA\@EA{\csname\@@XMLdata:#1\endcsname}%
+ \fi}
-\def\XMLprepend#1#2%
- {\edef\!!stringa{\@@XMLdata:#1}%
- \doifXMLdataelse{#1}%
- {\@EA\@EA\@EA\setvalue\@EA\@EA\@EA\!!stringa\@EA\@EA\@EA
- {#2\csname\!!stringa\endcsname}}
- {\setvalue\!!stringa{#2}}}
+\let\XMLpop \XMLflush
+
+\let\XMLpopdata\XMLflushdata
+
+\def\XMLappend#1#2% let to empty expands to nothing -)
+ {\long\@EA\edef\csname\@@XMLdata:#1\endcsname
+ {\csname\@@XMLdata:#1\endcsname#2}}
+
+\def\XMLprepend#1#2% let to empty expands to nothing -)
+ {\long\@EA\edef\csname\@@XMLdata:#1\endcsname
+ {#2\csname\@@XMLdata:#1\endcsname}}
\def\XMLerase#1%
- {\letvalue{\@@XMLdata:#1}\empty}
+ {\@EA\let\csname\@@XMLdata:#1\endcsname\longempty}
\def\XMLassign#1%
- {\setvalue{\@@XMLdata:#1}}
+ {\long\@EA\def\csname\@@XMLdata:#1\endcsname}
+
+\def\dontparseXMLelement#1>{}
+
+\def\simplifyXMLelements{\let\parseXMLelement\dontparseXMLelement}
\def\defXMLstring#1#2%
-% {\@EA\convertcommand\csname\@@XMLdata:#2\endcsname\to#1}
{\bgroup
+ \enableXMLexpansion
+ \simplifyXMLelements
\let\getXMLentity\firstofoneargument
+ \XMLrawentitiestrue
\xdef\@@XML@@string{\csname\@@XMLdata:#2\endcsname}%
- \egroup
- \@EA\convertcommand\@@XML@@string\to#1}
-
+ \egroup
+ \convertcommand\@@XML@@string\to#1}
+
+\def\defXMLclean#1#2%
+ {\bgroup
+ \enableXMLexpansion
+ \simplifyXMLelements
+ \simplifyXMLentities
+ \let\getXMLentity\expandedXMLentity % should this go in \simplify ?
+ \xdef\@@XML@@string{\csname\@@XMLdata:#2\endcsname}%
+ \egroup
+ \convertcommand\@@XML@@string\to#1}
+
\def\XMLshow#1%
- {\showvalue{\@@XMLdata:#1\endcsname}}
+ {\showvalue{\@@XMLdata:#1}}
-\def\XMLunspace#1%
- {\ifcsname\@@XMLdata:#1\endcsname
- \setevalue{\@@XMLdata:#1}%
- {\@EA\@EA\@EA\dounspaced\csname\@@XMLdata:#1\endcsname\end}%
+\def\XMLunspace#1% kan sneller
+ {\@EA\ifx\csname\@@XMLdata:#1\endcsname\longempty\else
+ \long\@EA\edef\csname\@@XMLdata:#1\csname
+ {\@EAEAEA\dounspaced\csname\@@XMLdata:#1\endcsname\end}%
\fi}
+\chardef\asciispacecode=32
+
\def\defXMLlowerclean#1% lowercase ! evt tzt upper too
{\bgroup
- \lccode`\#=32\lccode`\$=32\lccode`\%=32\lccode`\\=32\lccode`\^=32
- \lccode`\_=32\lccode`\{=32\lccode`\}=32\lccode`\|=32\lccode`\~=32
+ \lccode`\#\asciispacecode
+ \lccode`\$\asciispacecode
+ \lccode`\%\asciispacecode
+ \lccode`\\\asciispacecode
+ \lccode`\^\asciispacecode
+ \lccode`\_\asciispacecode
+ \lccode`\{\asciispacecode
+ \lccode`\}\asciispacecode
+ \lccode`\|\asciispacecode
+ \lccode`\~\asciispacecode
\@EA\lowercase\@EA{\@EA\xdef\@EA#1\@EA{#1}}%
\egroup}
@@ -791,36 +1570,17 @@
\def\mapXMLvalue#1#2#3% td align center -> middle
{\setvalue{\@@XMLvalue:#1:#2:#3}}
-% \def\XMLvar#1#2#3% td align center
-% {\ifundefined{\@@XMLvariable:#1:#2}%
-% \XMLval{#1}{#2}{#3}%
-% \else
-% \XMLval{#1}{#2}{\getvalue{\@@XMLvariable:#1:#2}}%
-% \fi}
-%
-% \def\XMLval#1#2#3%
-% {\ifundefined{\@@XMLvalue:#1:#2}%
-% #3%
-% \else
-% \getvalue{\@@XMLvalue:#1:#2}%
-% \fi}
-%
-% \def\XMLpar#1#2#3%
-% {\ifundefined{\@@XMLvariable:#1:#2}%
-% #3%
-% \else
-% \getvalue{\@@XMLvariable:#1:#2}%
-% \fi}
-%
-% speedup
-
\def\XMLvar#1#2#3% td align center
{\ifcsname\@@XMLvariable:#1:#2\endcsname
\XMLval{#1}{#2}{\csname\@@XMLvariable:#1:#2\endcsname}%
\else
- \XMLval{#1}{#2}{#3}% evt inline code
+ \XMLval{#1}{#2}{#3}% evt inline code
\fi}
+% \def\XMLvar#1#2#3% td align center
+% {\XMLval{#1}{#2}{\ifcsname\@@XMLvariable:#1:#2\endcsname
+% \csname\@@XMLvariable:#1:#2\endcsname\else#3\fi}}
+
\def\XMLval#1#2#3%
{\ifcsname\@@XMLvalue:#1:#2\endcsname
\csname\@@XMLvalue:#1:#2\endcsname
@@ -835,76 +1595,166 @@
#3%
\fi}
-% so far for speedup
+\def\XMLNSpar#1#2#3#4% element namespace name default
+ {\ifcsname\@@XMLvariable:#1:#2:#3\endcsname
+ \csname\@@XMLvariable:#1:#2:#3\endcsname
+ \else
+ #4%
+ \fi}
+
+\def\setXMLpar#1#2%
+ {\@EA\def\csname\@@XMLvariable:#1:#2\endcsname}
+
+\def\TEXpar#1#2%
+ {\csname#1\interfaced{#2}\endcsname}
-\defineXMLsingular [begingroup] {\begingroup}
-\defineXMLsingular [endgroup] {\endgroup}
+\let\texXMLpar\TEXpar % soon obsolete
+
+\let\XMLtex\TEXpar
+
+% handy one
+
+\def\XMLtyp#1#2#3%
+ {\ifcsname\@@XMLvariable:#1:#2\endcsname
+ \@EA\convertcommand\csname\@@XMLvariable:#1:#2\endcsname\to\ascii
+ \else
+ \convertargument#3\to\ascii
+ \fi
+ \ascii}
+
+\defineXMLsingular [begingroup] {\begingroup}
+\defineXMLsingular [endgroup] {\endgroup}
+\defineXMLsingular [gobblespacetokens] {\gobblespacetokens}
+\defineXMLsingular [disableXML] {\disableXML}
\def\XMLstr#1%
{{\enableXML\scantokens{#1}\unskip}}
-\def\XMLstr#1% test
- {\scantokens{\begingroup\enableXML#1<endgroup/>}}
-
-%\def\XMLstrpar#1#2#3%
-% {{\enableXML
-% \ifundefined{\@@XMLvariable:#1:#2}%
-% \scantokens{#3}%
-% \else
-% \scantokens\@EA\@EA\@EA
-% {\csname\@@XMLvariable:#1:#2\endcsname}\unskip
-% \fi}}
+\def\XMLstr#1% test
+ {\scantokens{\begingroup\enableXML#1<endgroup/>\gobblespacetokens}}
-\def\XMLstrpar#1#2#3% test
- {\ifundefined{\@@XMLvariable:#1:#2}%
+\def\XMLstrpar#1#2#3% test
+ {\ifcsname\@@XMLvariable:#1:#2\endcsname
+ \scantokens\@EAEAEA{\@EA\begingroup\@EA\enableXML
+ \csname\@@XMLvariable:#1:#2\endcsname<endgroup/>}%
+ \else
\scantokens{\begingroup\enableXML#3<endgroup/>}%
+ \fi}
+
+\def\doifXMLvarelse#1#2% geen etex, \relax too
+ {\ifcsname\@@XMLvariable:#1:#2\endcsname
+%\expandafter\ifx\csname\@@XMLvariable:#1:#2\endcsname\relax
+% \message{#1 #2 -> relax}\wait
+%\fi
+ \expandafter\ifx\csname\@@XMLvariable:#1:#2\endcsname\empty
+ \@EAEAEA\secondoftwoarguments
+ \else
+ \@EAEAEA\firstoftwoarguments
+ \fi
\else
- \scantokens\@EA\@EA\@EA{\@EA\begingroup\@EA\enableXML
- \csname\@@XMLvariable:#1:#2\endcsname<endgroup/>}%
+ \@EA\secondoftwoarguments
\fi}
-\def\doifXMLvarelse#1#2#3#4% geen etex, \relax too
- {\expandafter\ifx\csname\@@XMLvariable:#1:#2\endcsname\relax#4\else
- \expandafter\ifx\csname\@@XMLvariable:#1:#2\endcsname\empty#4\else#3\fi\fi}
+\def\doifXMLvar#1#2% geen etex, \relax too
+ {\ifcsname\@@XMLvariable:#1:#2\endcsname
+ \expandafter\ifx\csname\@@XMLvariable:#1:#2\endcsname\empty
+ \@EAEAEA\gobbleoneargument
+ \else
+ \@EAEAEA\firstofoneargument
+ \fi
+ \else
+ \@EA\gobbleoneargument
+ \fi}
-\def\doifXMLvalelse#1#2#3#4% geen etex, \relax too
- {\expandafter\ifx\csname\@@XMLvalue:#1:#2\endcsname\relax#4\else
- \expandafter\ifx\csname\@@XMLvalue:#1:#2\endcsname\empty#4\else#3\fi\fi}
+\def\doifXMLvalelse#1#2% geen etex, \relax too
+ {\ifcsname\@@XMLvalue:#1:#2\endcsname
+ \expandafter\ifx\csname\@@XMLvalue:#1:#2\endcsname\empty
+ \@EAEAEA\secondoftwoarguments
+ \else
+ \@EAEAEA\firstoftwoarguments
+ \fi
+ \else
+ \@EA\secondoftwoarguments
+ \fi}
\let\doifXMLparelse\doifXMLvarelse
+\let\doifXMLpar \doifXMLvar
+
+\bgroup \catcode`<=\@@active
-\def\dogotoXML%
- {\ifx\nexttoken<%
- \expandafter\nexttoken
- \else
- \expandafter\gotoXML
- \fi}
+\long\gdef\ignoreuntilXMLelement#1<{<}
+\long\gdef\grabuntilXMLelement #1<\to#2{\def#2{#1}<}
-\def\gotoXML%
- {\afterassignment\dogotoXML\let\nexttoken=}
+\egroup
-%D Saves tokens and typing.
+%D Saves tokens and typing.
-\def\XMLownvar {\XMLvar \currentXMLelement}
-\def\XMLownval {\XMLval \currentXMLelement}
-\def\XMLownpar {\XMLpar \currentXMLelement}
-\def\XMLownstrpar {\XMLstrpar \currentXMLelement}
-\def\doifXMLownvarelse{\doifXMLvarelse\currentXMLelement}
-\def\doifXMLownvalelse{\doifXMLvalelse\currentXMLelement}
-\def\doifXMLownparelse{\doifXMLparelse\currentXMLelement}
+\def\XMLownvar {\XMLvar {\rawXMLnamespace\rawXMLidentifier}}
+\def\XMLownval {\XMLval {\rawXMLnamespace\rawXMLidentifier}}
+\def\XMLownpar {\XMLpar {\rawXMLnamespace\rawXMLidentifier}}
+\def\XMLownstrpar {\XMLstrpar {\rawXMLnamespace\rawXMLidentifier}}
+\def\doifXMLownvarelse{\doifXMLvarelse{\rawXMLnamespace\rawXMLidentifier}}
+\def\doifXMLownvalelse{\doifXMLvalelse{\rawXMLnamespace\rawXMLidentifier}}
+\def\doifXMLownparelse{\doifXMLparelse{\rawXMLnamespace\rawXMLidentifier}}
+
+\def\ownXMLelement{\rawXMLnamespace\rawXMLidentifier}
-%D
+\def\XMLop#1% ownpar
+ {\csname\@@XMLvariable:\ownXMLelement:#1\endcsname}
+
+\def\XMLtp#1% texpar
+ {\csname\@@XMLmapmap\interfaced{#1}\endcsname}
+
+\def\doifelseXMLop#1{\doifelse{\XMLop{#1}}}
+\def\doifXMLop #1{\doif {\XMLop{#1}}}
+\def\doifnotXMLop #1{\doifnot {\XMLop{#1}}}
+
+\def\doifelsenothingXMLop#1{\doifelsenothing{\XMLop{#1}}}
+\def\doifsomethingXMLop #1{\doifsomething {\XMLop{#1}}}
+\def\doifnothingXMLop #1{\doifnothing {\XMLop{#1}}}
-\long\def\startXMLcode[#1] #2 \stopXMLcode
- {\setgvalue{\@@XMLcode:#1}{\startXMLdata#2\stopXMLdata}}
+\def\doifelseXMLtp#1{\doifelse{\XMLtp{#1}}}
+\def\doifXMLtp #1{\doif {\XMLtp{#1}}}
+\def\doifnotXMLtp #1{\doifnot {\XMLtp{#1}}}
+
+\def\doifelsenothingXMLtp#1{\doifelsenothing{\XMLtp{#1}}}
+\def\doifsomethingXMLtp #1{\doifsomething {\XMLtp{#1}}}
+\def\doifnothingXMLtp #1{\doifnothing {\XMLtp{#1}}}
+
+\def\XMLflushself{\csname\@@XMLdata:\ownXMLelement\endcsname}
+
+\def\XMLta {\theXMLarguments\@@XMLmapmap}
+\def\getXMLta {\expanded{\getparameters[\@@XMLmapmap][\XMLta]}}
+\def\expandXMLta{\expandXMLarguments\@@XMLmapmap}
+\def\expandXMLtp{\expandTEXpar\@@XMLmapmap} % #1
+
+\def\defXMLop#1#2{\@EA\let\@EA#1\csname\@@XMLvariable:\ownXMLelement:#2\endcsname}
+\def\defXMLtp#1#2{\@EA\let\@EA#1\csname\@@XMLmapmap\interfaced{#2}\endcsname}
+
+%D ...
+
+\def\protectXMLdata
+ {\catcode`\^^I\@@space
+ \catcode`\^^M\@@space
+ \catcode`\^^L\@@space
+ \catcode`\#\@@other}
+
+\long\def\startXMLcode
+ {\begingroup
+ \protectXMLdata
+ \dostartXMLcode}
+
+\long\def\dostartXMLcode[#1] #2 \stopXMLcode
+ {\@EA\gdef\csname\@@XMLcode:#1\endcsname{\startXMLdata#2\stopXMLdata}%
+ \endgroup}
\def\getXMLcode[#1]% \expandXMLcode
- {\getvalue{\@@XMLcode:#1}}
+ {\csname\@@XMLcode:#1\endcsname}
% \long\def\startXMLdata#1\stopXMLdata%
% {\begingroup\enableXML\scantokens{#1}\endgroup}
%
-% \defineXMLentity[tex-backslash] {\catchXMLpar}
+% \defineXMLentity[tex-backslash] {\catchXMLpar}
%
% \def\catchXMLpar#1#2#3
% {\if#1p\if#2a\if#3r\ifmmode\else\endgraf\fi
@@ -912,25 +1762,38 @@
\long\def\startXMLdata
{\begingroup
- \catcode`\^^I=\@@space
- \catcode`\^^M=\@@space
- \catcode`\^^L=\@@space
+ \protectXMLdata
\dostartXMLdata}
-
-% \long\def\dostartXMLdata#1\stopXMLdata
-% {\enableXML\scantokens{#1}\endgroup}
\long\def\dostartXMLdata#1\stopXMLdata
- {\enableXML\scantokens{#1}\ifhmode\unskip\unskip\fi\endgroup}
+ {\enableXML\scantokens{#1<gobblespacetokens/>}%
+ \endgroup
+ \ifhmode\unskip\unskip\fi}
+
+% suboptimal:
+%
+% \unexpanded\def\XMLdata#1% % \unexpanded added 22/5/2001
+% {\begingroup
+% \enableXML\scantokens{#1}\ifhmode\unskip\unskip\fi
+% \endgroup}
+%
+% better but does not work in tables:
+%
+% \unexpanded\def\XMLdata#1% % grouping changed 20/5/2001
+% {\scantokens{\begingroup\enableXML#1<endgroup/>\gobblespacetokens}}
+%
+% currently:
-\unexpanded\def\XMLdata#1% % \unexpanded added 22/5/2001
+\unexpanded\def\XMLdata % # safe
{\begingroup
- \enableXML\scantokens{#1}\ifhmode\unskip\unskip\fi
- \endgroup}
+ \protectXMLdata
+ \doXMLdata}
+
+\def\doXMLdata#1%
+ {\enableXML
+ \scantokens{#1<gobblespacetokens/>}%
+ \endgroup}
-\unexpanded\def\XMLdata#1% % grouping changed 20/5/2001
- {\scantokens{\begingroup\enableXML#1<endgroup/>}}
-
%D
\def\bXMLs{\ifignoreXMLspaces\ignorespaces\fi}
@@ -969,17 +1832,6 @@
\def\processXMLfile #1{\enableXML\processfile{#1}}
\def\processXMLfilegrouped#1{{\enableXML\processfile{#1}\relax\ifmmode\else\par\fi}}
-% partially defined here
-
-\fetchruntimecommand\showXMLfile {\f!xtagprefix\s!run}
-\fetchruntimecommand\showXMLbuffer{\f!xtagprefix\s!run}
-
-\fetchruntimecommand\showXMLtxt {\f!xtagprefix\s!run}
-\fetchruntimecommand\showXMLpar {\f!xtagprefix\s!run}
-\fetchruntimecommand\showXMLlin {\f!xtagprefix\s!run}
-\fetchruntimecommand\showXMLwrd {\f!xtagprefix\s!run}
-\fetchruntimecommand\showXMLemp {\f!xtagprefix\s!run}
-
%D \type
%D {processXMLbuffer}
%D
@@ -1003,6 +1855,8 @@
%D Loading specific modules takes place with \type
%D {\useXMLfilters}.
+% todo: flag
+
\def\useXMLfilter[#1]%
{\processcommalist[#1]\douseXMLfilter}
@@ -1018,141 +1872,112 @@
%D Temporarily here.
\newtoks\groupedtoks
+\newif\ifcollectXMLgrouped
-\bgroup
-
-\catcode`\<=\@@active
-
-\long\unexpanded\gdef\getXMLgrouped#1#2#3%
- {\groupedtoks\emptytoks
- \convertargument<#1>\to\xxascii
- \convertargument<#1 \to\yyascii
- \newcounter\groupedlevel
- \long\def\dogetgrouped##1</#1>%
- {\appendtoks##1\to\groupedtoks
- \convertargument##1\to\ascii
- \doloop
- {\@EA\@EA\@EA\aftersplitstring\@EA\ascii\@EA\at\xxascii\to\ascii
- \ifx\ascii\empty
- \exitloop
- \else
- \increment\groupedlevel
- \fi}%
- \convertargument##1\to\ascii
- \doloop
- {\@EA\@EA\@EA\aftersplitstring\@EA\ascii\@EA\at\yyascii\to\ascii
- \ifx\ascii\empty
- \exitloop
- \else
- \increment\groupedlevel
- \fi}%
- \ifnum\groupedlevel>0
- \decrement\groupedlevel
- \appendtoks</#1>\to\groupedtoks
- \else
- \edef\dogetgrouped{\noexpand#2\the\groupedtoks\noexpand#3}%
- \fi
- \dogetgrouped}%
- \dogetgrouped}
-
-%D Cleaner but hardly faster unless big strings are passed.
-
-\long\gdef\docountXMLgrouped#1\end#2\end
- {\long\def\dosplitstring##1#2##2@@##3\end%
- {\def\ascii{##2}%
- \ifx\ascii\empty \else
- \advance\scratchcounter 1
- \dosplitstring##2@@#2@@\end
- \fi}%
- \dosplitstring#1@@#2@@\end}
-
-\long\unexpanded\gdef\getXMLgrouped#1#2#3%
- {\groupedtoks\emptytoks
- \scratchcounter=0
- \long\def\dogetgrouped##1</#1>%
- {\appendtoks##1\to\groupedtoks
- \docountXMLgrouped##1\end<#1>\end
- \docountXMLgrouped##1\end<#1 \end
- \ifcase\scratchcounter
- \def\dogetgrouped{\@EA#2\the\groupedtoks#3}%
- \else
- \advance\scratchcounter -1
- \appendtoks</#1>\to\groupedtoks
- \fi
- \dogetgrouped}%
- \dogetgrouped}
+\bgroup \catcode`\<=\@@active
-%D More versatile.
+\newtoks\XMLgtoks
\long\unexpanded\gdef\getXMLgroupedenvironment#1#2#3%
- {\def\dodogetgrouped{\@EA#2\the\groupedtoks#3}%
+ {\collectXMLgroupedtrue
+ \XMLgtoks{#2}%
+ \long\def\dodogetgrouped{\@EA\the\@EA\XMLgtoks\the\groupedtoks#3}%
\getXMLgrouped{#1}}
\long\unexpanded\gdef\getXMLgroupedargument#1#2%
- {\def\dodogetgrouped{\@EA#2\@EA{\the\groupedtoks}}%
+ {\collectXMLgroupedtrue
+ \XMLgtoks{#2}%
+ \long\def\dodogetgrouped{\@EA\the\@EA\XMLgtoks\@EA{\the\groupedtoks}}%
+ \getXMLgrouped{#1}}
+
+\long\unexpanded\gdef\getXMLgroupedignore#1%
+ {\collectXMLgroupedfalse
+ \let\dodogetgrouped\relax
\getXMLgrouped{#1}}
-\long\unexpanded\gdef\getXMLgrouped#1%
+%\long\gdef\docountXMLgrouped#1\end#2\end % @@ => \relax\relax
+% {\long\def\dosplitstring##1#1##2@@##3\end%
+% {\def\ascii{##2}%
+% \ifx\ascii\empty \else
+% \advance\scratchcounter 1
+% \dosplitstring##2@@#1@@\end
+% \fi}%
+% \dosplitstring#2@@#1@@\end}
+
+\long\gdef\docountXMLgrouped#1\end#2\end % 1 relax is enough since it's
+ {\long\def\dosplitstring##1#1##2\relax\relax##3\end % another regime
+ {\def\ascii{##2}%
+ \ifx\ascii\empty \else
+ \advance\scratchcounter \plusone
+ \dosplitstring##2\relax\relax#1\relax\relax\end
+ \fi}%
+ \dosplitstring#2\relax\relax#1\relax\relax\end}
+
+\long\unexpanded\gdef\getXMLgrouped#1% #1 kan weg % klopt dit nu?
{\groupedtoks\emptytoks
\scratchcounter=0
- \long\def\dogetgrouped##1</#1>%
- {\appendtoks##1\to\groupedtoks
- \docountXMLgrouped##1\end<#1>\end
- \docountXMLgrouped##1\end<#1 \end
+ \edef\theXMLnamespace
+ {\ifx\originalXMLnamespace\empty\else\originalXMLnamespace:\fi
+ \currentXMLidentifier}%
+ \expanded{\long\noexpand\def\noexpand\dogetgrouped####1\noexpand</\currentXMLelement>}%
+ {\ifcollectXMLgrouped\appendtoks##1\to\groupedtoks\fi
+ \@EA\docountXMLgrouped\@EA<\theXMLnamespace>\end##1\end
+ \@EAEAEA\docountXMLgrouped\@EA\@EA\@EA<\@EA\theXMLnamespace\space \end##1\end
\ifcase\scratchcounter
\let\dogetgrouped\dodogetgrouped
\else
- \advance\scratchcounter -1
- \appendtoks</#1>\to\groupedtoks
+ \advance\scratchcounter \minusone
+ \ifcollectXMLgrouped\@EA\appendtoks\@EA<\@EA/\currentXMLelement>\to\groupedtoks\fi
\fi
\dogetgrouped}%
\dogetgrouped}
\egroup
-% {pre}{pos}{before}{after}
-%
-%\unexpanded\def\getgrouped#1#2#3#4%
-% {\groupedtoks\emptytoks
-% \convertargument#1\to\xxascii
-% \newcounter\groupedlevel
-% \def\dogetgrouped##1#2%
-% {\appendtoks##1\to\groupedtoks
-% \convertargument##1\to\ascii
-% \doloop
-% {\@EA\@EA\@EA\aftersplitstring\@EA\ascii\@EA\at\xxascii\to\ascii
-% \ifx\ascii\empty
-% \exitloop
-% \else
-% \increment\groupedlevel
-% \fi}%
-% \ifnum\groupedlevel>0
-% \decrement\groupedlevel
-% \appendtoks#2\to\groupedtoks
-% \else
-% \edef\dogetgrouped{\noexpand#3\the\groupedtoks\noexpand#4}%
-% \fi
-% \dogetgrouped}%
-% \dogetgrouped}
-
% interesting and fully expandable
-\def\XMLifequalelse#1#2#3#4#5%
- {\ifundefined{\@@XMLvariable:#1:#2}%
- #5%
+\def\XMLifequalelse#1#2#3%
+ {\ifcsname\@@XMLvariable:#1:#2\endcsname
+ \@EAEAEA\@@ifequal\csname\@@XMLvariable:#1:#2\endcsname\relax\@@and#3\relax\@@then
\else
- \@EA\@EA\@EA\@@ifequal\csname\@@XMLvariable:#1:#2\endcsname
- \relax\@@and#3\relax\@@then#4\@@else#5\@@fi
+ \@EA\secondoftwoarguments
\fi}
-\def\expifequalelse#1#2#3#4%
- {\@@ifequal#1\relax\relax\@@and#2\relax\relax\@@then#3\@@else#4\@@fi}
+\def\XMLownifequalelse#1#2%
+ {\@EAEAEA\@@ifequal\csname\@@XMLvariable:\ownXMLelement:#1\endcsname\relax\@@and#2\relax\@@then}
+
+\def\XMLyes#1{\XMLownifequalelse{#1}{yes}{#1}{}}
-\def\@@ifequal#1#2\@@and#3#4\@@then#5\@@else#6\@@fi%
+\def\expifequalelse#1#2%
+ {\@@ifequal#1\relax\relax\@@and#2\relax\relax\@@then}
+
+\def\@@ifequal#1#2\@@and#3%
{\ifx#1\relax
- \ifx#3\relax#5\else#6\fi
+ \ifx#3\relax
+ \@EAEAEA\@@if@@equal@@true
+ \else
+ \@EAEAEA\@@if@@equal@@false
+ \fi
\else
- \ifx#3\relax#6\else\@@ifequal#2\@@and#4\@@then#5\@@else#6\@@fi\fi
- \fi}
+ \ifx#3\relax
+ \@EAEAEAEAEAEA\@@if@@equal@@false
+ \else\ifx#1#3%
+ % go on
+ \else
+ \@EAEAEAEAEAEA\@@if@@equal@@false
+ \fi\fi
+ \fi
+ \@@ifequal#2\@@and}
+\long\def\@@if@@equal@@true #1\@@then#2#3{#2}
+\long\def\@@if@@equal@@false#1\@@then#2#3{#3}
+
+%D new stuff :
+
+\def\partialexpanded#1%
+ {\let\notexpanded\noexpand
+ \edef\@@expanded{\noexpand#1}%
+ \let\notexpanded\empty
+ \@@expanded}
+
\protect \endinput