%D \module %D [ file=lxml-ini, %D version=2007.08.17, %D title=\CONTEXT\ \XML\ Support, %D subtitle=Initialization, %D author=Hans Hagen, %D date=\currentdate, %D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] %C %C This module is part of the \CONTEXT\ macro||package and is %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. %D Todo: auto apply setups (manage at lua end) \writestatus{loading}{ConTeXt XML Support / Initialization} %registerctxluafile{lxml-tab}{1.001} % loader %registerctxluafile{lxml-lpt}{1.001} % parser %registerctxluafile{lxml-xml}{1.001} % xml finalizers %registerctxluafile{lxml-aux}{1.001} % extras using parser %registerctxluafile{lxml-mis}{1.001} % extras independent of parser \registerctxluafile{char-ent}{1.001} \registerctxluafile{lxml-ent}{1.001} % entity hacks \registerctxluafile{lxml-tex}{1.001} % tex finalizers \registerctxluafile{lxml-dir}{1.001} % ctx hacks \unprotect % todo \!!bs \!!es where handy (slower) \def\ctxlxml #1{\directlua\zerocount{lxml.#1}} \def\xmlmain #1{\ctxlxml{main("#1")}} \def\xmlmatch #1{\ctxlxml{match("#1")}} \def\xmlall #1#2{\ctxlxml{all("#1","#2")}} \def\xmlatt #1#2{\ctxlxml{att("#1","#2")}} \def\xmlattdef #1#2#3{\ctxlxml{att("#1","#2","#3")}} \def\xmlchainatt #1#2{\ctxlxml{chainattribute("#1","/","#2")}} \def\xmlchainattdef #1#2#3{\ctxlxml{chainattribute("#1","/","#2","#3")}} \def\xmlattribute #1#2#3{\ctxlxml{attribute("#1","#2","#3")}} \def\xmlattributedef #1#2#3#4{\ctxlxml{attribute("#1","#2","#3","#4")}} \def\xmlcommand #1#2#3{\ctxlxml{command("#1","#2","#3")}} \def\xmlconcat #1#2#3{\ctxlxml{concat("#1","#2",[[\detokenize{#3}]])}} \def\xmlconcatrange#1#2#3#4#5{\ctxlxml{concatrange("#1","#2","#3","#4",[[\detokenize{#5}]])}} \def\xmlcount #1#2{\ctxlxml{count("#1","#2")}} \def\xmldelete #1#2{\ctxlxml{delete("#1","#2")}} \def\xmldirectives #1{\ctxlxml{directives.setup("#1")}} \def\xmldirectivesbefore #1{\ctxlxml{directives.before("#1")}} \def\xmldirectivesafter #1{\ctxlxml{directives.after("#1")}} \def\xmlfilter #1#2{\ctxlxml{filter("#1",\!!bs#2\!!es)}} \def\xmlfilterlist #1#2{\ctxlxml{filterlist("#1",\!!bs#2\!!es)}} \def\xmlfunction #1#2{\ctxlxml{applyfunction("#1",\!!bs#2\!!es)}} \def\xmlfirst #1#2{\ctxlxml{first("#1","#2")}} \def\xmlflush #1{\ctxlxml{flush("#1")}} \def\xmlflushlinewise #1{\ctxlxml{flushlinewise("#1")}} \def\xmlflushspacewise #1{\ctxlxml{flushspacewise("#1")}} %def\xmlcontent #1{\ctxlxml{content("#1")}} %def\xmlflushstripped #1{\ctxlxml{strip("#1",true)}} \def\xmldirect #1{\ctxlxml{direct("#1")}} % in loops, not dt but root \def\xmlidx #1#2#3{\ctxlxml{idx("#1","#2",\number#3)}} \def\xmlinclude #1#2#3{\ctxlxml{include("#1","#2","#3",true)}} \def\xmlindex #1#2#3{\ctxlxml{index("#1","#2",\number#3)}} \def\xmlinfo #1{\hbox{\ttxx[\ctxlxml{info("#1")}]}} \def\xmlshow #1{\startpacked\ttx\xmlverbatim{#1}\stoppacked} \def\xmllast #1#2{\ctxlxml{last("#1","#2")}} \def\xmlname #1{\ctxlxml{name("#1")}} \def\xmlnamespace #1{\ctxlxml{namespace("#1")}} \def\xmlnonspace #1#2{\ctxlxml{nonspace("#1","#2")}} \def\xmlraw #1#2{\ctxlxml{raw("#1","#2")}} \def\xmlcontext #1#2{\ctxlxml{context("#1","#2")}} \def\xmlflushcontext #1{\ctxlxml{context("#1")}} \def\xmlsnippet #1#2{\ctxlxml{snippet("#1",#2)}} \def\xmlelement #1#2{\ctxlxml{element("#1",#2)}} \def\xmlregisterns #1#2{\ctxlua{xml.registerns("#1","#2")}} % document \def\xmlremapname #1#2#3#4{\ctxlua{xml.remapname(lxml.id("#1"),"#2","#3","#4")}} % element \def\xmlremapnamespace #1#2#3{\ctxlua{xml.renamespace(lxml.id("#1"),"#2","#3")}} % document \def\xmlchecknamespace #1#2#3{\ctxlua{xml.checknamespace(lxml.id("#1"),"#2","#3")}} % element \def\xmlsetfunction #1#2#3{\ctxlxml{setaction("#1","#2",#3)}} \def\xmlsetsetup #1#2#3{\ctxlxml{setsetup("#1","#2","#3")}} \def\xmlstrip #1#2{\ctxlxml{strip("#1","#2")}} \def\xmlstripnolines #1#2{\ctxlxml{strip("#1","#2",true)}} \def\xmlstripanywhere #1#2{\ctxlxml{strip("#1","#2",true,true)}} \def\xmlstripped #1#2{\ctxlxml{stripped("#1","#2")}} \def\xmlstrippednolines #1#2{\ctxlxml{stripped("#1","#2",true)}} \def\xmltag #1{\ctxlxml{tag("#1")}} \def\xmltext #1#2{\ctxlxml{text("#1","#2")}} \def\xmlverbatim #1{\ctxlxml{verbatim("#1")}} \def\xmldisplayverbatim #1{\ctxlxml{displayverbatim("#1")}} \def\xmlinlineverbatim #1{\ctxlxml{inlineverbatim("#1")}} \def\xmlload #1#2{\ctxlxml{load("#1","#2","\p_lxml_entities","\p_lxml_compress")}} \def\xmlloadbuffer #1#2{\ctxlxml{loadbuffer("#1","#2","\p_lxml_entities","\p_lxml_compress")}} \def\xmlloaddata #1#2{\ctxlxml{loaddata("#1",\!!bs#2\!!es,"\p_lxml_entities","\p_lxml_compress")}} \def\xmlloadregistered #1#2{\ctxlxml{loadregistered("#1","\p_lxml_entities","\p_lxml_compress")}} \def\xmlloaddirectives #1{\ctxlxml{directives.load("any:///#1")}} \def\xmlpos #1{\ctxlxml{pos("#1")}} \def\xmltoparameters #1{\ctxlxml{toparameters("#1")}} \def\xmltofile #1#2#3{\ctxlxml{tofile("#1","#2","#3")}} % id pattern filename % kind of special: \def\xmlstartraw{\ctxlxml{startraw()}} \def\xmlstopraw {\ctxlxml{stopraw()}} % todo: \xmldoifelseattribute \def\xmldoif #1#2{\ctxlxml{doif (\!!bs#1\!!es,\!!bs#2\!!es)}} % expandable \def\xmldoifnot #1#2{\ctxlxml{doifnot (\!!bs#1\!!es,\!!bs#2\!!es)}} % expandable \def\xmldoifelse #1#2{\ctxlxml{doifelse (\!!bs#1\!!es,\!!bs#2\!!es)}} % expandable \def\xmldoiftext #1#2{\ctxlxml{doiftext (\!!bs#1\!!es,\!!bs#2\!!es)}} % expandable \def\xmldoifnottext #1#2{\ctxlxml{doifnottext (\!!bs#1\!!es,\!!bs#2\!!es)}} % expandable \def\xmldoifelsetext #1#2{\ctxlxml{doifelsetext(\!!bs#1\!!es,\!!bs#2\!!es)}} % expandable %def\xmldoifelseempty #1#2{\ctxlxml{doifelseempty("#1","#2")}} % #2, "*" or "" == self not yet implemented %def\xmldoifelseselfempty #1{\ctxlxml{doifelseempty("#1")}} % \startxmlsetups xml:include % \xmlinclude{main}{include}{filename|href} % \stopxmlsetups % % \xmlprependsetup{xml:include} \let\xmlgrab\xmlsetsetup % obsolete \let\xmlself\s!unknown % obsolete \def\xmlsetup#1#2{\setupwithargument{#2}{#1}} \let\xmls\xmlsetup \let\xmlw\setupwithargument \newtoks \registeredxmlsetups % todo: 1:xml:whatever always before 3:xml:something \unexpanded\def\xmlprependsetup #1{\ctxlxml{installsetup(1,"*","#1")}} \unexpanded\def\xmlappendsetup #1{\ctxlxml{installsetup(2,"*","#1")}} \unexpanded\def\xmlbeforesetup #1#2{\ctxlxml{installsetup(3,"*","#1","#2")}} \unexpanded\def\xmlaftersetup #1#2{\ctxlxml{installsetup(4,"*","#1","#2")}} \unexpanded\def\xmlprependdocumentsetup #1#2{\ctxlxml{installsetup(1,"#1","#2")}} \unexpanded\def\xmlappenddocumentsetup #1#2{\ctxlxml{installsetup(2,"#1","#2")}} \unexpanded\def\xmlbeforedocumentsetup#1#2#3{\ctxlxml{installsetup(3,"#1","#2","#3")}} \unexpanded\def\xmlafterdocumentsetup #1#2#3{\ctxlxml{installsetup(4,"#1","#2","#3")}} \unexpanded\def\xmlremovesetup #1{\ctxlxml{removesetup("*","#1")}} \unexpanded\def\xmlremovedocumentsetup #1#2{\ctxlxml{removesetup("#1","#2")}} \unexpanded\def\xmlflushdocumentsetups #1#2{\ctxlxml{flushsetups("#1","*","#2")}} % #1 == id where to apply * and #2 \unexpanded\def\xmlresetdocumentsetups #1{\ctxlxml{resetsetups("#1")}} \let\xmlregistersetup \xmlappendsetup \let\xmlregisterdocumentsetup\xmlappenddocumentsetup \def\xmldocument{main} \unexpanded\def\xmlregisteredsetups {\xmlstarttiming \xmlflushsetups \xmldefaulttotext\xmldocument % after include \xmlstoptiming} \unexpanded\def\xmlregistereddocumentsetups#1#2% id setups {\xmlstarttiming % todo: test for duplicates ! \xmlflushdocumentsetups{#1}{#2}% \xmldefaulttotext{#1}% after include \xmlstoptiming} \unexpanded\def\xmlstarttiming{\ctxlua{statistics.starttiming(lxml)}} \unexpanded\def\xmlstoptiming {\ctxlua{statistics.stoptiming (lxml)}} \def\lxml_process#1#2#3#4#5% flag \loader id name what initializersetup {\begingroup \edef\xmldocument{#3}% #2 can be \xmldocument and set as such %xmlpushdocument{#3}% #2{#3}{#4}% \setcatcodetable\notcatcodes \doifelsenothing{#5} {\xmlsetup{#3}{xml:process}} {\xmlsetup{#3}{#5}}% %xmlpopdocument \endgroup} \unexpanded\def\xmlprocessfile {\lxml_process\plusone \xmlload} \unexpanded\def\xmlprocessdata {\lxml_process\zerocount\xmlloaddata} \unexpanded\def\xmlprocessbuffer {\lxml_process\zerocount\xmlloadbuffer} \unexpanded\def\xmlprocessregistered{\lxml_process\zerocount\xmlloadregistered} \let\xmlprocess \xmlprocessfile \startxmlsetups xml:flush \xmlflush{#1} \stopxmlsetups \startxmlsetups xml:process \xmlregistereddocumentsetups{#1}{#1} \xmlmain{#1} \stopxmlsetups \unexpanded\def\xmlloadonly#1#2#3% {\xmlload{#1}{#2}% \xmlregistereddocumentsetups{#1}{#3}} % beware: \xmlmain takes the real root, so also processing % instructions preceding the root element; well, in some % sense that is the root \unexpanded\def\xmlconnect#1#2#3% inefficient {\scratchcounter\xmlcount{#1}{#2}\relax \ifcase\scratchcounter \or \xmlall{#1}{#2}% \else \dorecurse \scratchcounter {\ifnum\recurselevel>\plusone#3\fi \xmlidx{#1}{#2}\recurselevel}% \fi} \unexpanded\def\xmlcdataobeyedline {\obeyedline} \unexpanded\def\xmlcdataobeyedspace{\strut\obeyedspace} \unexpanded\def\xmlcdatabefore {\bgroup\tt} \unexpanded\def\xmlcdataafter {\egroup} % verbatim (dodo:pre/post whitespace, maybe splot verbatim and % cdata commands), experimental: % % \xmlsetfunction{main}{verbatim}{lxml.displayverbatim} % \xmlsetfunction{main}{verb} {lxml.inlineverbatim} % \unexpanded\def\startxmldisplayverbatim[#1]{} % \unexpanded\def\stopxmldisplayverbatim {} % \unexpanded\def\startxmlinlineverbatim [#1]{} % \unexpanded\def\stopxmlinlineverbatim {} % we use an xml: namespace so one has to define a suitable verbatim, say % % \definetyping[xml:verbatim][typing] % % this is experimental! \unexpanded\def\startxmldisplayverbatim[#1]% {\startpacked % \begingroup \edef\currenttyping{xml:#1}% \unexpanded\def\stopxmldisplayverbatim {\endofverbatimlines \stoppacked} % \endgroup \doinitializeverbatim \beginofverbatimlines} \unexpanded\def\startxmlinlineverbatim[#1]% {\begingroup \edef\currenttype{xml:#1}% \let\stopxmldisplayverbatim\endgroup \doinitializeverbatim} % will move but is developed for xml \newtoks \collectingtoks \unexpanded\def\startcollect#1\stopcollect {\collectingtoks\@EA{\the\collectingtoks#1}} \unexpanded\def\startexpandedcollect#1\stopexpandedcollect {\normalexpanded{\collectingtoks{\the\collectingtoks#1}}} \unexpanded\def\startcollecting{\collectingtoks\emptytoks} \unexpanded\def\stopcollecting {\the\collectingtoks} \def\inlinemessage #1{\dontleavehmode{\tttf#1}} \def\displaymessage#1{\blank\inlinemessage{#1}\blank} % \def\xmltraceentities % settextcleanup is not defined % {\ctxlua{xml.settextcleanup(lxml.trace_text_entities)}% % \appendtoks\ctxlxml{showtextentities()}\to\everygoodbye} % processing instructions \def\xmlcontextdirective#1% kind class key value {\executeifdefined{xml#1directive}\gobblethreearguments} % setting up xml: % % \setupxml[\c!default=] % mkiv only == text % \setupxml[\c!default=\v!none] % mkiv only, undefined -> hidden % \setupxml[\c!default=\v!text] % mkiv only, undefined -> text % \def\xmlctxdirective#1#2#3{\doif{#1}{clue}{\doif{#2}{page}}{\page[#3]}} \newconstant\xmlprocessingmode % 0=unset, 1=text, 2=hidden \installcorenamespace{xml} \installcorenamespace{xmldefaults} \installcorenamespace{xmlmapvalue} \installdirectcommandhandler \??xml {xml} \letvalue{\??xmldefaults\v!normal}\zerocount \letvalue{\??xmldefaults\v!none }\zerocount \letvalue{\??xmldefaults\v!text }\plusone \letvalue{\??xmldefaults\v!hidden}\plustwo \unexpanded\def\xmldefaulttotext#1% {\ifcase\xmlprocessingmode % unset \or \ctxlxml{setcommandtotext("#1")}% 1 \or \ctxlxml{setcommandtonone("#1")}% 2 \else % unset \fi} \appendtoks \xmlprocessingmode\executeifdefined{\??xmldefaults\directxmlparameter\c!default}\plusone \to \everysetupxml \unexpanded\def\initializexmlprocessing % is this still needed? {\the\everysetupxml} \let\p_lxml_entities\empty \let\p_lxml_compress\empty \appendtoks \edef\p_lxml_entities{\directxmlparameter\c!entities}% \edef\p_lxml_compress{\directxmlparameter\c!compress}% \to \everysetupxml \setupxml [\c!default=, % flush all \c!compress=\v!no, % strip comment \c!entities=\v!yes] % replace entities \def\xmlmapvalue #1#2#3{\setvalue{\??xmlmapvalue#1:#2}{#3}} % keep #3 to grab spaces \def\xmlvalue #1#2#3{\executeifdefined{\??xmlmapvalue#1:#2}{#3}} %def\xmlvalue #1#2{\ifcsname\??xmlmapvalue#1:#2\endcsname\csname\??xmlmapvalue#1:#2\expandafter\expandafter\gobbleoneargument\expandafter\endcsname\else\expandafter\firstofoneargument\fi} \def\xmldoifelsevalue #1#2{\ifcsname\??xmlmapvalue#1:#2\endcsname\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi} \let\xmlmapval\xmlmapvalue \let\xmlval \xmlvalue %D Experimental: \def\xmlgetindex #1{\ctxlxml{getindex("\xmldocument","#1")}} \def\xmlrawindex #1{\ctxlxml{rawindex("#1")}} \def\xmlwithindex #1#2{\ctxlxml{withindex("\xmldocument","#1","#2")}} \def\xmlreference #1#2{\string\xmlwithindex{#1}{#2}} %D Entities (might change): \setnewconstant\xmlautoentities\plusone % 0=off, 1=upper, 2=upper,lower \def\xmlsetentity#1#2{\ctxlua{xml.registerentity('#1',\!!bs\detokenize{#2}\!!es)}} \def\xmltexentity#1#2{\ctxlua{lxml.registerentity('#1',\!!bs\detokenize{#2}\!!es)}} % \xmlsetentity{tex}{\TEX{}} % {} needed \unexpanded\def\xmle {\ifcase\xmlautoentities \expandafter\lxml_e_none \or \expandafter\lxml_e_upper \or \expandafter\lxml_e_upperlower \else \expandafter\lxml_e_none \fi} \def\lxml_e_none#1#2% safe {#1} \def\lxml_e_upper#1#2% can be abbreviation {\ifcsname#2\endcsname \csname#2\expandafter\endcsname \else #1% \fi} \def\lxml_e_upperlower#1#2% can be anything, so unsafe {\ifcsname#2\endcsname \csname#2\expandafter\endcsname \else\ifcsname#1\endcsname \csname#1\expandafter\expandafter\expandafter\endcsname \else #1% \fi\fi} % handy helpers (analogue to MP and LUA and TEX and also MkII) \unexpanded\def\processXMLbuffer {\dosingleempty\lxml_process_buffer} \def\lxml_process_buffer[#1]% {\xmlprocessbuffer{temp}{#1}{}} \unexpanded\def\processXMLfile#1% {\xmlprocessfile{temp}{#1}{}} \unexpanded\def\XMLdata#1% {\xmlprocessdata{temp}{#1}{}} \let\processxmlbuffer\processXMLbuffer \let\processxmlfile \processXMLfile \let\xmldata \XMLdata \protect \endinput % \newcount\charactersactiveoffset \charactersactiveoffset="10000 % % \startextendcatcodetable\ctxcatcodes % \catcode\numexpr\charactersactiveoffset+`<\relax=13 % \catcode\numexpr\charactersactiveoffset+`&\relax=13 % \catcode\numexpr\charactersactiveoffset+`>\relax=13 % \stopextendcatcodetable % % \startextendcatcodetable\xmlcatcodes % not needed % \catcode\numexpr\charactersactiveoffset+`<\relax=13 % \catcode\numexpr\charactersactiveoffset+`&\relax=13 % \catcode\numexpr\charactersactiveoffset+`>\relax=13 % \stopextendcatcodetable % % \ctxlua { % entities are remembered in the format % characters.remapentity("<",characters.activeoffset + utf.byte("<")) % characters.remapentity("&",characters.activeoffset + utf.byte("&")) % characters.remapentity(">",characters.activeoffset + utf.byte(">")) % }