diff options
author | Hans Hagen <pragma@wxs.nl> | 2002-01-11 00:00:00 +0100 |
---|---|---|
committer | Hans Hagen <pragma@wxs.nl> | 2002-01-11 00:00:00 +0100 |
commit | 736de6a312c37fbb8cea65cf0a86eda7dbbe0575 (patch) | |
tree | ad6691db97ee31450f9ca5b30a90a22df067331b /tex/context/base/xtag-ini.tex | |
parent | 398264e8338d79fc389c76f0a1f0b30e4442f4e3 (diff) | |
download | context-736de6a312c37fbb8cea65cf0a86eda7dbbe0575.tar.gz |
stable 2002.01.11
Diffstat (limited to 'tex/context/base/xtag-ini.tex')
-rw-r--r-- | tex/context/base/xtag-ini.tex | 1949 |
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 &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="Óblaébla&tex;and$andüziezoྙ" /> +% \stopXMLdata +% +% \defineXMLentity[45]{|it works|} % {|-|} +% +% \startXMLdata +% text-.text +% textEFtext +% \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 |