summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/context/documents/general/manuals/luatex.pdfbin1507388 -> 1507651 bytes
-rw-r--r--doc/context/documents/general/manuals/xml-mkiv.pdfbin1353055 -> 1008282 bytes
-rw-r--r--doc/context/documents/general/qrcs/setup-cs.pdfbin840827 -> 840828 bytes
-rw-r--r--doc/context/documents/general/qrcs/setup-de.pdfbin840039 -> 840051 bytes
-rw-r--r--doc/context/documents/general/qrcs/setup-en.pdfbin844589 -> 844592 bytes
-rw-r--r--doc/context/documents/general/qrcs/setup-fr.pdfbin839047 -> 839047 bytes
-rw-r--r--doc/context/documents/general/qrcs/setup-it.pdfbin842291 -> 842296 bytes
-rw-r--r--doc/context/documents/general/qrcs/setup-mapping-cs.pdfbin345548 -> 345550 bytes
-rw-r--r--doc/context/documents/general/qrcs/setup-mapping-de.pdfbin428714 -> 428717 bytes
-rw-r--r--doc/context/documents/general/qrcs/setup-mapping-en.pdfbin343059 -> 343063 bytes
-rw-r--r--doc/context/documents/general/qrcs/setup-mapping-fr.pdfbin345589 -> 345593 bytes
-rw-r--r--doc/context/documents/general/qrcs/setup-mapping-it.pdfbin344246 -> 344247 bytes
-rw-r--r--doc/context/documents/general/qrcs/setup-mapping-nl.pdfbin343327 -> 343329 bytes
-rw-r--r--doc/context/documents/general/qrcs/setup-mapping-ro.pdfbin598014 -> 598015 bytes
-rw-r--r--doc/context/documents/general/qrcs/setup-nl.pdfbin835084 -> 835122 bytes
-rw-r--r--doc/context/documents/general/qrcs/setup-ro.pdfbin837566 -> 837557 bytes
-rw-r--r--doc/context/sources/general/manuals/luatex/luatex-modifications.tex4
-rw-r--r--doc/context/sources/general/manuals/xml/xml-mkiv-commands.tex893
-rw-r--r--doc/context/sources/general/manuals/xml/xml-mkiv-contents.tex12
-rw-r--r--doc/context/sources/general/manuals/xml/xml-mkiv-converter.tex300
-rw-r--r--doc/context/sources/general/manuals/xml/xml-mkiv-examples.tex948
-rw-r--r--doc/context/sources/general/manuals/xml/xml-mkiv-expressions.tex645
-rw-r--r--doc/context/sources/general/manuals/xml/xml-mkiv-filtering.tex262
-rw-r--r--doc/context/sources/general/manuals/xml/xml-mkiv-introduction.tex42
-rw-r--r--doc/context/sources/general/manuals/xml/xml-mkiv-lookups.tex314
-rw-r--r--doc/context/sources/general/manuals/xml/xml-mkiv-lpath.tex207
-rw-r--r--doc/context/sources/general/manuals/xml/xml-mkiv-style.tex155
-rw-r--r--doc/context/sources/general/manuals/xml/xml-mkiv-titlepage.tex47
-rw-r--r--doc/context/sources/general/manuals/xml/xml-mkiv-tricks.tex814
-rw-r--r--doc/context/sources/general/manuals/xml/xml-mkiv.tex4382
-rw-r--r--metapost/context/base/mpiv/mp-blob.mpiv22
-rw-r--r--metapost/context/base/mpiv/mp-grph.mpiv2
-rw-r--r--metapost/context/base/mpiv/mp-luas.mpiv77
-rw-r--r--metapost/context/base/mpiv/mp-mlib.mpiv83
-rw-r--r--metapost/context/base/mpiv/mp-page.mpiv2
-rw-r--r--metapost/context/base/mpiv/mp-tool.mpiv8
-rw-r--r--tex/context/base/mkii/cont-new.mkii2
-rw-r--r--tex/context/base/mkii/context.mkii2
-rw-r--r--tex/context/base/mkii/mult-de.mkii2
-rw-r--r--tex/context/base/mkiv/attr-ini.mkiv26
-rw-r--r--tex/context/base/mkiv/buff-ini.lua2
-rw-r--r--tex/context/base/mkiv/buff-ini.mkiv8
-rw-r--r--tex/context/base/mkiv/buff-ver.mkiv6
-rw-r--r--tex/context/base/mkiv/cldf-ini.lua25
-rw-r--r--tex/context/base/mkiv/cldf-ver.lua87
-rw-r--r--tex/context/base/mkiv/cont-new.mkiv16
-rw-r--r--tex/context/base/mkiv/context.mkiv2
-rw-r--r--tex/context/base/mkiv/grph-inc.lua6
-rw-r--r--tex/context/base/mkiv/meta-blb.lua30
-rw-r--r--tex/context/base/mkiv/meta-ini.lua8
-rw-r--r--tex/context/base/mkiv/meta-nod.lua76
-rw-r--r--tex/context/base/mkiv/meta-nod.mkiv16
-rw-r--r--tex/context/base/mkiv/mlib-lua.lua1122
-rw-r--r--tex/context/base/mkiv/mlib-pps.lua53
-rw-r--r--tex/context/base/mkiv/mlib-pps.mkiv7
-rw-r--r--tex/context/base/mkiv/mult-prm.mkiv2
-rw-r--r--tex/context/base/mkiv/mult-sys.mkiv1
-rw-r--r--tex/context/base/mkiv/page-ini.mkiv5
-rw-r--r--tex/context/base/mkiv/scrp-ini.mkiv21
-rw-r--r--tex/context/base/mkiv/status-files.pdfbin26033 -> 26025 bytes
-rw-r--r--tex/context/base/mkiv/status-lua.pdfbin262591 -> 262992 bytes
-rw-r--r--tex/context/base/mkiv/strc-not.mkvi41
-rw-r--r--tex/context/base/mkiv/syst-ini.mkiv7
-rw-r--r--tex/context/base/mkiv/typo-dir.mkiv12
-rw-r--r--tex/context/base/mkiv/typo-mar.mkiv1
-rw-r--r--tex/context/interface/mkii/keys-de.xml2
-rw-r--r--tex/context/interface/mkiv/i-context.pdfbin844589 -> 844592 bytes
-rw-r--r--tex/context/interface/mkiv/i-readme.pdfbin61058 -> 61061 bytes
-rw-r--r--tex/context/modules/mkiv/x-setups-overview.mkiv9
-rw-r--r--tex/generic/context/luatex/luatex-pdf.tex4
70 files changed, 5689 insertions, 5131 deletions
diff --git a/doc/context/documents/general/manuals/luatex.pdf b/doc/context/documents/general/manuals/luatex.pdf
index d24fd65c0..9cf5e932b 100644
--- a/doc/context/documents/general/manuals/luatex.pdf
+++ b/doc/context/documents/general/manuals/luatex.pdf
Binary files differ
diff --git a/doc/context/documents/general/manuals/xml-mkiv.pdf b/doc/context/documents/general/manuals/xml-mkiv.pdf
index f8b8c34c2..6508f2ecc 100644
--- a/doc/context/documents/general/manuals/xml-mkiv.pdf
+++ b/doc/context/documents/general/manuals/xml-mkiv.pdf
Binary files differ
diff --git a/doc/context/documents/general/qrcs/setup-cs.pdf b/doc/context/documents/general/qrcs/setup-cs.pdf
index 1380998c0..99f1cce8e 100644
--- a/doc/context/documents/general/qrcs/setup-cs.pdf
+++ b/doc/context/documents/general/qrcs/setup-cs.pdf
Binary files differ
diff --git a/doc/context/documents/general/qrcs/setup-de.pdf b/doc/context/documents/general/qrcs/setup-de.pdf
index ffda60e11..5024d4ec1 100644
--- a/doc/context/documents/general/qrcs/setup-de.pdf
+++ b/doc/context/documents/general/qrcs/setup-de.pdf
Binary files differ
diff --git a/doc/context/documents/general/qrcs/setup-en.pdf b/doc/context/documents/general/qrcs/setup-en.pdf
index c92ba194a..e12fb62d5 100644
--- a/doc/context/documents/general/qrcs/setup-en.pdf
+++ b/doc/context/documents/general/qrcs/setup-en.pdf
Binary files differ
diff --git a/doc/context/documents/general/qrcs/setup-fr.pdf b/doc/context/documents/general/qrcs/setup-fr.pdf
index e7ae18eda..3c8f9d85d 100644
--- a/doc/context/documents/general/qrcs/setup-fr.pdf
+++ b/doc/context/documents/general/qrcs/setup-fr.pdf
Binary files differ
diff --git a/doc/context/documents/general/qrcs/setup-it.pdf b/doc/context/documents/general/qrcs/setup-it.pdf
index c44b7defc..72ff7fd90 100644
--- a/doc/context/documents/general/qrcs/setup-it.pdf
+++ b/doc/context/documents/general/qrcs/setup-it.pdf
Binary files differ
diff --git a/doc/context/documents/general/qrcs/setup-mapping-cs.pdf b/doc/context/documents/general/qrcs/setup-mapping-cs.pdf
index ffd8d2127..431448870 100644
--- a/doc/context/documents/general/qrcs/setup-mapping-cs.pdf
+++ b/doc/context/documents/general/qrcs/setup-mapping-cs.pdf
Binary files differ
diff --git a/doc/context/documents/general/qrcs/setup-mapping-de.pdf b/doc/context/documents/general/qrcs/setup-mapping-de.pdf
index d4e801f0a..c3cf3fa4e 100644
--- a/doc/context/documents/general/qrcs/setup-mapping-de.pdf
+++ b/doc/context/documents/general/qrcs/setup-mapping-de.pdf
Binary files differ
diff --git a/doc/context/documents/general/qrcs/setup-mapping-en.pdf b/doc/context/documents/general/qrcs/setup-mapping-en.pdf
index 81eb49286..fe1e5d5fe 100644
--- a/doc/context/documents/general/qrcs/setup-mapping-en.pdf
+++ b/doc/context/documents/general/qrcs/setup-mapping-en.pdf
Binary files differ
diff --git a/doc/context/documents/general/qrcs/setup-mapping-fr.pdf b/doc/context/documents/general/qrcs/setup-mapping-fr.pdf
index 1f7e467f5..048f2440a 100644
--- a/doc/context/documents/general/qrcs/setup-mapping-fr.pdf
+++ b/doc/context/documents/general/qrcs/setup-mapping-fr.pdf
Binary files differ
diff --git a/doc/context/documents/general/qrcs/setup-mapping-it.pdf b/doc/context/documents/general/qrcs/setup-mapping-it.pdf
index 7b13337ce..3e69835e6 100644
--- a/doc/context/documents/general/qrcs/setup-mapping-it.pdf
+++ b/doc/context/documents/general/qrcs/setup-mapping-it.pdf
Binary files differ
diff --git a/doc/context/documents/general/qrcs/setup-mapping-nl.pdf b/doc/context/documents/general/qrcs/setup-mapping-nl.pdf
index 90177e867..08d14f24c 100644
--- a/doc/context/documents/general/qrcs/setup-mapping-nl.pdf
+++ b/doc/context/documents/general/qrcs/setup-mapping-nl.pdf
Binary files differ
diff --git a/doc/context/documents/general/qrcs/setup-mapping-ro.pdf b/doc/context/documents/general/qrcs/setup-mapping-ro.pdf
index f4c443e86..0185a98c9 100644
--- a/doc/context/documents/general/qrcs/setup-mapping-ro.pdf
+++ b/doc/context/documents/general/qrcs/setup-mapping-ro.pdf
Binary files differ
diff --git a/doc/context/documents/general/qrcs/setup-nl.pdf b/doc/context/documents/general/qrcs/setup-nl.pdf
index 14f885db1..d1f2b6477 100644
--- a/doc/context/documents/general/qrcs/setup-nl.pdf
+++ b/doc/context/documents/general/qrcs/setup-nl.pdf
Binary files differ
diff --git a/doc/context/documents/general/qrcs/setup-ro.pdf b/doc/context/documents/general/qrcs/setup-ro.pdf
index a8f773569..c17e699a1 100644
--- a/doc/context/documents/general/qrcs/setup-ro.pdf
+++ b/doc/context/documents/general/qrcs/setup-ro.pdf
Binary files differ
diff --git a/doc/context/sources/general/manuals/luatex/luatex-modifications.tex b/doc/context/sources/general/manuals/luatex/luatex-modifications.tex
index b1b803d48..50d23fb1b 100644
--- a/doc/context/sources/general/manuals/luatex/luatex-modifications.tex
+++ b/doc/context/sources/general/manuals/luatex/luatex-modifications.tex
@@ -572,7 +572,7 @@ something (as it comes from the backend it's normally a sequence of tokens).
\stopsubsection
-\startsubsection[title={\lpr{pdfextension}, \lpr {pdfvariable} and \lpr {pdffeedback}}]
+\startsubsection[title={\lpr{pdfextension}, \lpr {pdfvariable} and \lpr {pdffeedback}},reference=sec:pdfextensions]
In order for \LUATEX\ to be more than just \TEX\ you need to enable primitives. That
has already been the case right from the start. If you want the traditional \PDFTEX\
@@ -643,6 +643,7 @@ The configuration related registers have become:
\edef\pdfignoreunknownimages {\pdfvariable ignoreunknownimages}
\edef\pdfgentounicode {\pdfvariable gentounicode}
\edef\pdfomitcidset {\pdfvariable omitcidset}
+\edef\pdfomitcharset {\pdfvariable omitcharset}
\edef\pdfpagebox {\pdfvariable pagebox}
\edef\pdfminorversion {\pdfvariable minorversion}
\edef\pdfuniqueresname {\pdfvariable uniqueresname}
@@ -891,6 +892,7 @@ The engine sets the following defaults.
\pdfignoreunknownimages 0
\pdfgentounicode 0
\pdfomitcidset 0
+\pdfomitcharset 0
\pdfpagebox 0
\pdfminorversion 4
\pdfuniqueresname 0
diff --git a/doc/context/sources/general/manuals/xml/xml-mkiv-commands.tex b/doc/context/sources/general/manuals/xml/xml-mkiv-commands.tex
new file mode 100644
index 000000000..ab9989895
--- /dev/null
+++ b/doc/context/sources/general/manuals/xml/xml-mkiv-commands.tex
@@ -0,0 +1,893 @@
+\environment xml-mkiv-style
+
+\startcomponent xml-mkiv-commands
+
+\startchapter[title={Commands}]
+
+\startsection[title={nodes and lpaths}]
+
+The amount of commands available for manipulating the \XML\ file is rather large.
+Many of the commands cooperate with the already discussed setups, a fancy name
+for a collection of macro calls either or not mixed with text.
+
+Most of the commands are just shortcuts to \LUA\ calls, which means that the real
+work is done by \LUA. In fact, what happens is that we have a continuous transfer
+of control from \TEX\ to \LUA, where \LUA\ prints back either data (like element
+content or attribute values) or just invokes a setup whereby it passes a
+reference to the node resolved conform the path expression. The invoked setup
+itself might return control to \LUA\ again, etc.
+
+This sounds complicated but examples will show what we mean here. First we
+present the whole repertoire of commands. Because users can read the source code,
+they might uncover more commands, but only the ones discussed here are official.
+The commands are grouped in categories.
+
+In the following sections \cmdinternal {cd:node} means a reference to a node:
+this can be the identifier of the root (the loaded xml tree) or a reference to a
+node in that tree (often the result of some lookup. A \cmdinternal {cd:lpath} is
+a fancy name for a path expression (as with \XSLT) but resolved by \LUA.
+
+\stopsection
+
+\startsection[title={commands}]
+
+There are a lot of commands available but you probably can ignore most of them.
+We try to be complete which means that there is for instance \type {\xmlfirst} as
+well as \type {\xmllast} but you probably never need the last one. There are also
+commands that were used when testing this interface and we see no reason to
+remove them. Some obscure ones are used in modules and after a while even I often
+forget that they exist. To give you an idea of what commands are important we
+show their use in generating the \CONTEXT\ command definitions (\type
+{x-set-11.mkiv}) per January 2016:
+
+\startcolumns[n=2,balance=yes]
+\starttabulate[|l|r|]
+\NC \type {\xmlall} \NC 1 \NC \NR
+\NC \type {\xmlatt} \NC 23 \NC \NR
+\NC \type {\xmlattribute} \NC 1 \NC \NR
+\NC \type {\xmlcount} \NC 1 \NC \NR
+\NC \type {\xmldoif} \NC 2 \NC \NR
+\NC \type {\xmldoifelse} \NC 1 \NC \NR
+\NC \type {\xmlfilterlist} \NC 4 \NC \NR
+\NC \type {\xmlflush} \NC 5 \NC \NR
+\NC \type {\xmlinclude} \NC 1 \NC \NR
+\NC \type {\xmlloadonly} \NC 1 \NC \NR
+\NC \type {\xmlregisterdocumentsetup} \NC 1 \NC \NR
+\NC \type {\xmlsetsetup} \NC 1 \NC \NR
+\NC \type {\xmlsetup} \NC 4 \NC \NR
+\stoptabulate
+\stopcolumns
+
+As you can see filtering, flushing and accessing attributes score high. Below we show
+the statistics of a quite complex rendering (5 variants of schoolbooks: basic book,
+answers, teachers guide, worksheets, full blown version with extensive tracing).
+
+\startcolumns[n=2,balance=yes]
+\starttabulate[|l|r|]
+\NC \type {\xmladdindex} \NC 3 \NC \NR
+\NC \type {\xmlall} \NC 5 \NC \NR
+\NC \type {\xmlappendsetup} \NC 1 \NC \NR
+\NC \type {\xmlapplyselectors} \NC 1 \NC \NR
+\NC \type {\xmlatt} \NC 40 \NC \NR
+\NC \type {\xmlattdef} \NC 9 \NC \NR
+\NC \type {\xmlattribute} \NC 10 \NC \NR
+\NC \type {\xmlbadinclusions} \NC 3 \NC \NR
+\NC \type {\xmlconcat} \NC 3 \NC \NR
+\NC \type {\xmlcount} \NC 1 \NC \NR
+\NC \type {\xmldelete} \NC 11 \NC \NR
+\NC \type {\xmldoif} \NC 39 \NC \NR
+\NC \type {\xmldoifelse} \NC 28 \NC \NR
+\NC \type {\xmldoifelsetext} \NC 13 \NC \NR
+\NC \type {\xmldoifnot} \NC 2 \NC \NR
+\NC \type {\xmldoifnotselfempty} \NC 1 \NC \NR
+\NC \type {\xmlfilter} \NC 100 \NC \NR
+\NC \type {\xmlfirst} \NC 51 \NC \NR
+\NC \type {\xmlflush} \NC 69 \NC \NR
+\NC \type {\xmlflushcontext} \NC 2 \NC \NR
+\NC \type {\xmlinclude} \NC 1 \NC \NR
+\NC \type {\xmlincludeoptions} \NC 5 \NC \NR
+\NC \type {\xmlinclusion} \NC 16 \NC \NR
+\NC \type {\xmlinjector} \NC 1 \NC \NR
+\NC \type {\xmlloaddirectives} \NC 1 \NC \NR
+\NC \type {\xmlmapvalue} \NC 4 \NC \NR
+\NC \type {\xmlmatch} \NC 1 \NC \NR
+\NC \type {\xmlprependsetup} \NC 5 \NC \NR
+\NC \type {\xmlregisterdocumentsetup} \NC 2 \NC \NR
+\NC \type {\xmlregistersetup} \NC 1 \NC \NR
+\NC \type {\xmlremapnamespace} \NC 1 \NC \NR
+\NC \type {\xmlsetfunction} \NC 2 \NC \NR
+\NC \type {\xmlsetinjectors} \NC 2 \NC \NR
+\NC \type {\xmlsetsetup} \NC 11 \NC \NR
+\NC \type {\xmlsetup} \NC 76 \NC \NR
+\NC \type {\xmlstrip} \NC 1 \NC \NR
+\NC \type {\xmlstripanywhere} \NC 1 \NC \NR
+\NC \type {\xmltag} \NC 1 \NC \NR
+\NC \type {\xmltext} \NC 53 \NC \NR
+\NC \type {\xmlvalue} \NC 2 \NC \NR
+\stoptabulate
+\stopcolumns
+
+Here many more are used but this is an exceptional case. The top is again
+dominated by filtering, flushing and attribute consulting. The list can actually
+be smaller. For instance, the \type {\xmlcount} can just as well be \type
+{\xmlfilter} with a \type {count} finalizer. There are also some special ones,
+like the injectors, that are needed for finetuning the final result.
+
+\stopsection
+
+\startsection[title={loading}]
+
+\startxmlcmd {\cmdbasicsetup{xmlloadfile}}
+ loads the file \cmdinternal {cd:file} and registers it under \cmdinternal
+ {cd:name} and applies either given or standard \cmdinternal
+ {cd:xmlsetup} (alias: \type {\xmlload})
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlloadbuffer}}
+ loads the buffer \cmdinternal {cd:buffer} and registers it under
+ \cmdinternal {cd:name} and applies either given or standard
+ \cmdinternal {cd:xmlsetup}
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlloaddata}}
+ loads \cmdinternal {cd:text} and registers it under \cmdinternal
+ {cd:name} and applies either given or standard \cmdinternal
+ {cd:xmlsetup}
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlloadonly}}
+ loads \cmdinternal {cd:text} and registers it under \cmdinternal
+ {cd:name} and applies either given or standard \cmdinternal
+ {cd:xmlsetup} but doesn't flush the content
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlinclude}}
+ includes the file specified by attribute \cmdinternal {cd:name} of the
+ element located by \cmdinternal {cd:lpath} at node \cmdinternal {cd:node}
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlprocessfile}}
+ registers file \cmdinternal {cd:file} as \cmdinternal {cd:name} and
+ process the tree starting with \cmdinternal {cd:xmlsetup} (alias:
+ \type {\xmlprocess})
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlprocessbuffer}}
+ registers buffer \cmdinternal {cd:name} as \cmdinternal {cd:name} and process
+ the tree starting with \cmdinternal {cd:xmlsetup}
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlprocessdata}}
+ registers \cmdinternal {cd:text} as \cmdinternal {cd:name} and process
+ the tree starting with \cmdinternal {cd:xmlsetup}
+\stopxmlcmd
+
+The initial setup defaults to \type {xml:process} that is defined
+as follows:
+
+\starttyping
+\startsetups xml:process
+ \xmlregistereddocumentsetups\xmldocument
+ \xmlmain\xmldocument
+\stopsetups
+\stoptyping
+
+First we apply the setups associated with the document (including common setups)
+and then we flush the whole document. The macro \type {\xmldocument} expands to
+the current document id. There is also \type {\xmlself} which expands to the
+current node number (\type {#1} in setups).
+
+\startxmlcmd {\cmdbasicsetup{xmlmain}}
+ returns the whole document
+\stopxmlcmd
+
+Normally such a flush will trigger a chain reaction of setups associated with the
+child elements.
+
+\stopsection
+
+\startsection[title={saving}]
+
+\startxmlcmd {\cmdbasicsetup{xmlsave}}
+ saves the given node \cmdinternal {cd:node} in the file \cmdinternal {cd:file}
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmltofile}}
+ saves the match of \cmdinternal {cd:lpath} in the file \cmdinternal {cd:file}
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmltobuffer}}
+ saves the match of \cmdinternal {cd:lpath} in the buffer \cmdinternal {cd:buffer}
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmltobufferverbose}}
+ saves the match of \cmdinternal {cd:lpath} verbatim in the buffer \cmdinternal
+ {cd:buffer}
+\stopxmlcmd
+
+% \startxmlcmd {\cmdbasicsetup{xmltoparameters}}
+% converts the match of \cmdinternal {cd:lpath} to key|/|values (for tracing)
+% \stopxmlcmd
+
+The next command is only needed when you have messed with the tree using
+\LUA\ code.
+
+\startxmlcmd {\cmdbasicsetup{xmladdindex}}
+ (re)indexes a tree
+\stopxmlcmd
+
+The following macros are only used in special situations and are not really meant
+for users.
+
+\startxmlcmd {\cmdbasicsetup{xmlraw}}
+ flush the content if \cmdinternal {cd:node} with original entities
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{startxmlraw}}
+ flush the wrapped content with original entities
+\stopxmlcmd
+
+\stopsection
+
+\startsection[title={flushing data}]
+
+When we flush an element, the associated \XML\ setups are expanded. The most
+straightforward way to flush an element is the following. Keep in mind that the
+returned values itself can trigger setups and therefore flushes.
+
+\startxmlcmd {\cmdbasicsetup{xmlflush}}
+ returns all nodes under \cmdinternal {cd:node}
+\stopxmlcmd
+
+You can restrict flushing by using commands that accept a specification.
+
+\startxmlcmd {\cmdbasicsetup{xmltext}}
+ returns the text of the matching \cmdinternal {cd:lpath} under \cmdinternal
+ {cd:node}
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlpure}}
+ returns the text of the matching \cmdinternal {cd:lpath} under \cmdinternal
+ {cd:node} without \type {\Ux} escaped special \TEX\ characters
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlflushtext}}
+ returns the text of the \cmdinternal {cd:node}
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlflushpure}}
+ returns the text of the \cmdinternal {cd:node} without \type {\Ux} escaped
+ special \TEX\ characters
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlnonspace}}
+ returns the text of the matching \cmdinternal {cd:lpath} under \cmdinternal
+ {cd:node} without embedded spaces
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlall}}
+ returns all nodes under \cmdinternal {cd:node} that matches \cmdinternal
+ {cd:lpath}
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmllastmatch}}
+ returns all nodes found in the last match
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlfirst}}
+ returns the first node under \cmdinternal {cd:node} that matches \cmdinternal
+ {cd:lpath}
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmllast}}
+ returns the last node under \cmdinternal {cd:node} that matches \cmdinternal
+ {cd:lpath}
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlfilter}}
+ at a match of \cmdinternal {cd:lpath} a given filter \type {filter} is applied
+ and the result is returned
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlsnippet}}
+ returns the \cmdinternal {cd:number}\high{th} element under \cmdinternal
+ {cd:node}
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlposition}}
+ returns the \cmdinternal {cd:number}\high{th} match of \cmdinternal
+ {cd:lpath} at node \cmdinternal {cd:node}; a negative number starts at the
+ end (alias: \type {\xmlindex})
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlelement}}
+ returns the \cmdinternal {cd:number}\high{th} child of node \cmdinternal {cd:node};
+ a negative number starts at the end
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlpos}}
+ returns the index (position) in the parent node of \cmdinternal {cd:node}
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlconcat}}
+ returns the sequence of nodes that match \cmdinternal {cd:lpath} at
+ \cmdinternal {cd:node} whereby \cmdinternal {cd:text} is put between each
+ match
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlconcatrange}}
+ returns the \cmdinternal {cd:first}\high {th} upto \cmdinternal
+ {cd:last}\high {th} of nodes that match \cmdinternal {cd:lpath} at
+ \cmdinternal {cd:node} whereby \cmdinternal {cd:text} is put between each
+ match
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlcommand}}
+ apply the given \cmdinternal {cd:xmlsetup} to each match of \cmdinternal
+ {cd:lpath} at node \cmdinternal {cd:node}
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlstrip}}
+ remove leading and trailing spaces from nodes under \cmdinternal {cd:node}
+ that match \cmdinternal {cd:lpath}
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlstripped}}
+ remove leading and trailing spaces from nodes under \cmdinternal {cd:node}
+ that match \cmdinternal {cd:lpath} and return the content afterwards
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlstripnolines}}
+ remove leading and trailing spaces as well as collapse embedded spaces
+ from nodes under \cmdinternal {cd:node} that match \cmdinternal {cd:lpath}
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlstrippednolines}}
+ remove leading and trailing spaces as well as collapse embedded spaces from
+ nodes under \cmdinternal {cd:node} that match \cmdinternal {cd:lpath} and
+ return the content afterwards
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlverbatim}}
+ flushes the content verbatim code (without any wrapping, i.e. no fonts
+ are selected and such)
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlinlineverbatim}}
+ return the content of the node as inline verbatim code; no further
+ interpretation (expansion) takes place and spaces are honoured; it uses the
+ following wrapper
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{startxmlinlineverbatim}}
+ wraps inline verbatim mode using the environment specified (a prefix \type
+ {xml:} is added to the environment name)
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmldisplayverbatim}}
+ return the content of the node as display verbatim code; no further
+ interpretation (expansion) takes place and leading and trailing spaces and
+ newlines are treated special; it uses the following wrapper
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{startxmldisplayverbatim}}
+ wraps the content in display verbatim using the environment specified (a prefix
+ \type {xml:} is added to the environment name)
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlprettyprint}}
+ pretty print (with colors) the node \cmdinternal {cd:node}; use the \CONTEXT\
+ \SCITE\ lexers when available (\type {\usemodule [scite]})
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlflushspacewise}}
+ flush node \cmdinternal {cd:node} obeying spaces and newlines
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlflushlinewise}}
+ flush node \cmdinternal {cd:node} obeying newlines
+\stopxmlcmd
+
+\stopsection
+
+\startsection[title={information}]
+
+The following commands return strings. Normally these are used in tests.
+
+\startxmlcmd {\cmdbasicsetup{xmlname}}
+ returns the complete name (including namespace prefix) of the
+ given \cmdinternal {cd:node}
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlnamespace}}
+ returns the namespace of the given \cmdinternal {cd:node}
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmltag}}
+ returns the tag of the element, without namespace prefix
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlcount}}
+ returns the number of matches of \cmdinternal {cd:lpath} at node \cmdinternal
+ {cd:node}
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlatt}}
+ returns the value of attribute \cmdinternal {cd:name} or empty if no such
+ attribute exists
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlattdef}}
+ returns the value of attribute \cmdinternal {cd:name} or \cmdinternal
+ {cd:string} if no such attribute exists
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlrefatt}}
+ returns the value of attribute \cmdinternal {cd:name} or empty if no such
+ attribute exists; a leading \type {#} is removed (nicer for tex)
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlchainatt}}
+ returns the value of attribute \cmdinternal {cd:name} or empty if no such
+ attribute exists; backtracks till a match is found
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlchainattdef}}
+ returns the value of attribute \cmdinternal {cd:name} or \cmdinternal
+ {cd:string} if no such attribute exists; backtracks till a match is found
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlattribute}}
+ finds a first match for \cmdinternal {cd:lpath} at \cmdinternal {cd:node} and
+ returns the value of attribute \cmdinternal {cd:name} or empty if no such
+ attribute exists
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlattributedef}}
+ finds a first match for \cmdinternal {cd:lpath} at \cmdinternal {cd:node} and
+ returns the value of attribute \cmdinternal {cd:name} or \cmdinternal
+ {cd:text} if no such attribute exists
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmllastatt}}
+ returns the last attribute found (this avoids a lookup)
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlsetatt}}
+ set the value of attribute \cmdinternal {cd:name}
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlsetattribute}}
+ set the value of attribute \cmdinternal {cd:name} for each match of \cmdinternal
+ {cd:lpath}
+\stopxmlcmd
+
+\stopsection
+
+\startsection[title={manipulation}]
+
+You can use \LUA\ code to manipulate the tree and it makes no sense to duplicate
+this in \TEX. In the future we might provide an interface to some of this
+functionality. Keep in mind that manipuating the tree might have side effects as
+we maintain several indices into the tree that also needs to be updated then.
+
+\stopsection
+
+\startsection[title={integration}]
+
+If you write a module that deals with \XML, for instance processing cals tables,
+then you need ways to control specific behaviour. For instance, you might want to
+add a background to the table. Such directives are collected in \XML\ files and
+can be loaded on demand.
+
+\startxmlcmd {\cmdbasicsetup{xmlloaddirectives}}
+ loads \CONTEXT\ directives from \cmdinternal {cd:file} that will get
+ interpreted when processing documents
+\stopxmlcmd
+
+A directives definition file looks as follows:
+
+\starttyping
+<?xml version="1.0" standalone="yes"?>
+
+<directives>
+ <directive attribute='id' value="100"
+ setup="cdx:100"/>
+ <directive attribute='id' value="101"
+ setup="cdx:101"/>
+ <directive attribute='cdx' value="colors" element="cals:table"
+ setup="cdx:cals:table:colors"/>
+ <directive attribute='cdx' value="vertical" element="cals:table"
+ setup="cdx:cals:table:vertical"/>
+ <directive attribute='cdx' value="noframe" element="cals:table"
+ setup="cdx:cals:table:noframe"/>
+ <directive attribute='cdx' value="*" element="cals:table"
+ setup="cdx:cals:table:*"/>
+</directives>
+\stoptyping
+
+Examples of usage can be found in \type {x-cals.mkiv}. The directive is triggered
+by an attribute. Instead of a setup you can specify a setup to be applied before
+and after the node gets flushed.
+
+\startxmlcmd {\cmdbasicsetup{xmldirectives}}
+ apply the setups directive associated with the node
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmldirectivesbefore}}
+ apply the before directives associated with the node
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmldirectivesafter}}
+ apply the after directives associated with the node
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlinstalldirective}}
+ defines a directive that hooks into a handler
+\stopxmlcmd
+
+Normally a directive will be put in the \XML\ file, for instance as:
+
+\starttyping
+<?context-mathml-directive minus reduction yes ?>
+\stoptyping
+
+Here the \type {mathml} is the general class of directives and \type {minus} a
+subclass, in our case a specific element.
+
+\stopsection
+
+\startsection[title={setups}]
+
+The basic building blocks of \XML\ processing are setups. These are just
+collections of macros that are expanded. These setups get one argument passed
+(\type {#1}):
+
+\starttyping
+\startxmlsetups somedoc:somesetup
+ \xmlflush{#1}
+\stopxmlsetups
+\stoptyping
+
+This argument is normally a number that internally refers to a specific node in
+the \XML\ tree. The user should see it as an abstract reference and not depend on
+its numeric property. Just think of it as \quote {the current node}. You can (and
+probably will) call such setups using:
+
+\startxmlcmd {\cmdbasicsetup{xmlsetup}}
+ expands setup \cmdinternal {cd:setup} and pass \cmdinternal {cd:node} as
+ argument
+\stopxmlcmd
+
+However, in most cases the setups are associated to specific elements,
+something that users of \XSLT\ might recognize as templates.
+
+\startxmlcmd {\cmdbasicsetup{xmlsetfunction}}
+ associates function \cmdinternal {cd:luafunction} to the elements in
+ namespace \cmdinternal {cd:name} that match \cmdinternal {cd:lpath}
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlsetsetup}}
+ associates setups \cmdinternal {cd:setup} (\TEX\ code) with the matching
+ nodes of \cmdinternal {cd:lpath} or root \cmdinternal {cd:node}
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlprependsetup}}
+ pushes \cmdinternal {cd:setup} to the front of global list of setups
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlappendsetup}}
+ adds \cmdinternal {cd:setup} to the global list of setups to be applied
+ (alias: \type{\xmlregistersetup})
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlbeforesetup}}
+ pushes \cmdinternal {cd:setup} into the global list of setups; the
+ last setup is the position
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlaftersetup}}
+ adds \cmdinternal {cd:setup} to the global list of setups; the last setup
+ is the position
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlremovesetup}}
+ removes \cmdinternal {cd:setup} from the global list of setups
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlprependdocumentsetup}}
+ pushes \cmdinternal {cd:setup} to the front of list of setups to be applied
+ to \cmdinternal {cd:name}
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlappenddocumentsetup}}
+ adds \cmdinternal {cd:setup} to the list of setups to be applied to
+ \cmdinternal {cd:name} (you can also use the alias: \type
+ {\xmlregisterdocumentsetup})
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlbeforedocumentsetup}}
+ pushes \cmdinternal {cd:setup} into the setups to be applied to \cmdinternal
+ {cd:name}; the last setup is the position
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlafterdocumentsetup}}
+ adds \cmdinternal {cd:setup} to the setups to be applied to \cmdinternal
+ {cd:name}; the last setup is the position
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlremovedocumentsetup}}
+ removes \cmdinternal {cd:setup} from the global list of setups to be applied
+ to \cmdinternal {cd:name}
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlresetsetups}}
+ removes all global setups
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlresetdocumentsetups}}
+ removes all setups from the \cmdinternal {cd:name} specific list of setups to
+ be applied
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlflushdocumentsetups}{setup}}
+ applies \cmdinternal {cd:setup} (can be a list) to \cmdinternal {cd:name}
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlregisteredsetups}}
+ applies all global setups to the current document
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlregistereddocumentsetups}}
+ applies all document specific \cmdinternal {cd:setup} to document
+ \cmdinternal {cd:name}
+\stopxmlcmd
+
+\stopsection
+
+\startsection[title={testing}]
+
+The following test macros all take a \cmdinternal {cd:node} as first argument
+and an \cmdinternal {cd:lpath} as second:
+
+\startxmlcmd {\cmdbasicsetup{xmldoif}}
+ expands to \cmdinternal {cd:true} when \cmdinternal {cd:lpath} matches at
+ node \cmdinternal {cd:node}
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmldoifnot}}
+ expands to \cmdinternal {cd:true} when \cmdinternal {cd:lpath} does not match
+ at node \cmdinternal {cd:node}
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmldoifelse}}
+ expands to \cmdinternal {cd:true} when \cmdinternal {cd:lpath} matches at
+ node \cmdinternal {cd:node} and to \cmdinternal {cd:false} otherwise
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmldoiftext}}
+ expands to \cmdinternal {cd:true} when the node matching \cmdinternal
+ {cd:lpath} at node \cmdinternal {cd:node} has some content
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmldoifnottext}}
+ expands to \cmdinternal {cd:true} when the node matching \cmdinternal
+ {cd:lpath} at node \cmdinternal {cd:node} has no content
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmldoifelsetext}}
+ expands to \cmdinternal {cd:true} when the node matching \cmdinternal
+ {cd:lpath} at node \cmdinternal {cd:node} has content and to \cmdinternal
+ {cd:false} otherwise
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmldoifatt}}
+ expands to \cmdinternal {cd:true} when the attribute matching \cmdinternal
+ {cd:node} and the name given as second argument matches the third argument
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmldoifnotatt}}
+ expands to \cmdinternal {cd:true} when the attribute matching \cmdinternal
+ {cd:node} and the name given as second argument differs from the third
+ argument
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmldoifelseatt}}
+ expands to \cmdinternal {cd:true} when the attribute matching \cmdinternal
+ {cd:node} and the name given as second argument matches the third argument
+ and to \cmdinternal {cd:false} otherwise
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmldoifelseempty}}
+ expands to \cmdinternal {cd:true} when the node matching \cmdinternal
+ {cd:lpath} at node \cmdinternal {cd:node} is empty and to \cmdinternal
+ {cd:false} otherwise
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmldoifelseselfempty}}
+ expands to \cmdinternal {cd:true} when the node is empty and to \cmdinternal
+ {cd:false} otherwise
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmldoifselfempty}}
+ expands to \cmdinternal {cd:true} when \cmdinternal {cd:node} is empty
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmldoifnotselfempty}}
+ expands to \cmdinternal {cd:true} when \cmdinternal {cd:node} is not empty
+\stopxmlcmd
+
+\stopsection
+
+\startsection[title={initialization}]
+
+The general setup command (not to be confused with setups) that deals with the
+\MKIV\ tree handler is \type {\setupxml}. There are currently only a few options.
+
+\cmdfullsetup{setupxml}
+
+When you set \type {default} to \cmdinternal {cd:text} elements with no setup
+assigned will end up as text. When set to \type {hidden} such elements will be
+hidden. You can apply the default yourself using:
+
+\startxmlcmd {\cmdbasicsetup{xmldefaulttotext}}
+ presets the tree with root \cmdinternal {cd:node} to the handlers set up with
+ \type {\setupxml} option \cmdinternal{default}
+\stopxmlcmd
+
+You can set \type {compress} to \type {yes} in which case comment is stripped
+from the tree when the file is read.
+
+\startxmlcmd {\cmdbasicsetup{xmlregisterns}}
+ associates an internal namespace (like \type {mml}) with one given in the
+ document as \URL\ (like mathml)
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlremapname}}
+ changes the namespace and tag of the matching elements
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlremapnamespace}}
+ replaces all references to the given namespace to a new one (applied
+ recursively)
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlchecknamespace}}
+ sets the namespace of the matching elements unless a namespace is already set
+\stopxmlcmd
+
+\stopsection
+
+\startsection[title={helpers}]
+
+Often an attribute will determine the rendering and this may result in many
+tests. Especially when we have multiple attributes that control the output such
+tests can become rather extensive and redundant because one gets $n\times m$ or
+more such tests.
+
+Therefore we have a convenient way to map attributes onto for instance strings or
+commands.
+
+\startxmlcmd {\cmdbasicsetup{xmlmapvalue}}
+ associate a \cmdinternal {cd:text} with a \cmdinternal {cd:category} and
+ \cmdinternal {cd:name} (alias: \type{\xmlmapval})
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlvalue}}
+ expand the value associated with a \cmdinternal {cd:category} and
+ \cmdinternal {cd:name} and if not resolved, expand to the \cmdinternal
+ {cd:text} (alias: \type{\xmlval})
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmldoifelsevalue}}
+ associate a \cmdinternal {cd:text} with a \cmdinternal {cd:category} and
+ \cmdinternal {cd:name}
+\stopxmlcmd
+
+This is used as follows. We define a couple of mappings in the same category:
+
+\starttyping
+\xmlmapvalue{emph}{bold} {\bf}
+\xmlmapvalue{emph}{italic}{\it}
+\stoptyping
+
+Assuming that we have associated the following setup with the \type {emph}
+element, we can say (with \type {#1} being the current element):
+
+\starttyping
+\startxmlsetups demo:emph
+ \begingroup
+ \xmlvalue{emph}{\xmlatt{#1}{type}}{}
+ \endgroup
+\stopxmlsetups
+\stoptyping
+
+In this case we have no default. The \type {type} attribute triggers the actions,
+as in:
+
+\starttyping
+normal <emph type='bold'>bold</emph> normal
+\stoptyping
+
+This mechanism is not really bound to elements and attributes so you can use this
+mechanism for other purposes as well.
+
+\stopsection
+
+\startsection[title={Parameters}]
+
+\startbuffer[test]
+<something whatever="alpha">
+ <what>
+ beta
+ </what>
+</something>
+\stopbuffer
+
+\startbuffer
+\startxmlsetups xml:mysetups
+ \xmlsetsetup{\xmldocument}{*}{xml:*}
+\stopxmlsetups
+
+\xmlregistersetup{xml:mysetups}
+
+\startxmlsetups xml:something
+ parameter : \xmlpar {#1}{whatever}\par
+ attribute : \xmlatt {#1}{whatever}\par
+ text : \xmlfirst {#1}{what} \par
+ \xmlsetpar{#1}{whatever}{gamma}
+ parameter : \xmlpar {#1}{whatever}\par
+ \xmlflush{#1}
+\stopxmlsetups
+
+\startxmlsetups xml:what
+ what: \xmlflush{#1}\par
+ parameter : \xmlparam{#1}{..}{whatever}\par
+\stopxmlsetups
+
+\xmlprocessbuffer{main}{test}{}
+\stopbuffer
+
+Say that we have this \XML\ blob:
+
+\typebuffer[test]
+
+With:
+
+\typebuffer
+
+we get:
+
+\getbuffer
+
+Parameters are stored with a node.
+
+\startxmlcmd {\cmdbasicsetup{xmlpar}}
+ returns the value of parameter \cmdinternal {cd:name} or empty if no such
+ parameter exists
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlparam}}
+ finds a first match for \cmdinternal {cd:lpath} at \cmdinternal {cd:node} and
+ returns the value of parameter \cmdinternal {cd:name} or empty if no such
+ parameter exists
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmllastpar}}
+ returns the last parameter found (this avoids a lookup)
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlsetpar}}
+ set the value of parameter \cmdinternal {cd:name}
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlsetparam}}
+ set the value of parameter \cmdinternal {cd:name} for each match of \cmdinternal
+ {cd:lpath}
+\stopxmlcmd
+
+\stopsection
+
+\stopchapter
+
+\stopcomponent
diff --git a/doc/context/sources/general/manuals/xml/xml-mkiv-contents.tex b/doc/context/sources/general/manuals/xml/xml-mkiv-contents.tex
new file mode 100644
index 000000000..e0787ec5f
--- /dev/null
+++ b/doc/context/sources/general/manuals/xml/xml-mkiv-contents.tex
@@ -0,0 +1,12 @@
+\environment xml-mkiv-style
+
+\startcomponent xml-mkiv-contents
+
+\starttitle[title=Contents]
+
+\placelist
+ [chapter,section]
+
+\stoptitle
+
+\stopcomponent
diff --git a/doc/context/sources/general/manuals/xml/xml-mkiv-converter.tex b/doc/context/sources/general/manuals/xml/xml-mkiv-converter.tex
new file mode 100644
index 000000000..a457f962b
--- /dev/null
+++ b/doc/context/sources/general/manuals/xml/xml-mkiv-converter.tex
@@ -0,0 +1,300 @@
+\environment xml-mkiv-style
+
+\startcomponent xml-mkiv-converter
+
+\startchapter[title={Setting up a converter}]
+
+\startsection[title={from structure to setup}]
+
+We use a very simple document structure for demonstrating how a converter is
+defined. In practice a mapping will be more complex, especially when we have a
+style with complex chapter openings using data coming from all kind of places,
+different styling of sections with the same name, selectively (out of order)
+flushed content, special formatting, etc.
+
+\typefile{manual-demo-1.xml}
+
+Say that this document is stored in the file \type {demo.xml}, then the following
+code can be used as starting point:
+
+\starttyping
+\startxmlsetups xml:demo:base
+ \xmlsetsetup{#1}{document|section|p}{xml:demo:*}
+\stopxmlsetups
+
+\xmlregisterdocumentsetup{demo}{xml:demo:base}
+
+\startxmlsetups xml:demo:document
+ \starttitle[title={Contents}]
+ \placelist[chapter]
+ \stoptitle
+ \xmlflush{#1}
+\stopxmlsetups
+
+\startxmlsetups xml:demo:section
+ \startchapter[title=\xmlfirst{#1}{/title}]
+ \xmlfirst{#1}{/content}
+ \stopchapter
+\stopxmlsetups
+
+\startxmlsetups xml:demo:p
+ \xmlflush{#1}\endgraf
+\stopxmlsetups
+
+\xmlprocessfile{demo}{demo.xml}{}
+\stoptyping
+
+Watch out! These are not just setups, but specific \XML\ setups which get an
+argument passed (the \type {#1}). If for some reason your \XML\ processing fails,
+it might be that you mistakenly have used a normal setup definition. The argument
+\type {#1} represents the current node (element) and is a unique identifier. For
+instance a \type {<p>..</p>} can have an identifier {demo::5}. So, we can get
+something:
+
+\starttyping
+\xmlflush{demo::5}\endgraf
+\stoptyping
+
+but as well:
+
+\starttyping
+\xmlflush{demo::6}\endgraf
+\stoptyping
+
+Keep in mind that the references tor the actual nodes (elements) are
+abstractions, you never see those \type {<id>::<number>}'s, because we will use
+either the abstract \type {#1} (any node) or an explicit reference like \type
+{demo}. The previous setup when issued will be like:
+
+\starttyping
+\startchapter[title=\xmlfirst{demo::3}{/title}]
+ \xmlfirst{demo::4}{/content}
+\stopchapter
+\stoptyping
+
+Here the \type {title} is used to typeset the chapter title but also for an entry
+in the table of contents. At the moment the title is typeset the \XML\ node gets
+looked up and expanded in real text. However, for the list it gets stored for
+later use. One can argue that this is not needed for \XML, because one can just
+filter all the titles and use page references, but then one also looses the
+control one normally has over such titles. For instance it can be that some
+titles are rendered differently and for that we need to keep track of usage.
+Doing that with transformations or filtering is often more complex than leaving
+that to \TEX. As soon as the list gets typeset, the reference (\type {demo::#3})
+is used for the lookup. This is because by default the title is stored as given.
+So, as long as we make sure the \XML\ source is loaded before the table of
+contents is typeset we're ok. Later we will look into this in more detail, for
+now it's enough to know that in most cases the abstract \type {#1} reference will
+work out ok.
+
+Contrary to the style definitions this interface looks rather low level (with no
+optional arguments) and the main reason for this is that we want processing to be
+fast. So, the basic framework is:
+
+\starttyping
+\startxmlsetups xml:demo:base
+ % associate setups with elements
+\stopxmlsetups
+
+\xmlregisterdocumentsetup{demo}{xml:demo:base}
+
+% define setups for matches
+
+\xmlprocessfile{demo}{demo.xml}{}
+\stoptyping
+
+In this example we mostly just flush the content of an element and in the case of
+a section we flush explicit child elements. The \type {#1} in the example code
+represents the current element. The line:
+
+\starttyping
+\xmlsetsetup{demo}{*}{-}
+\stoptyping
+
+sets the default for each element to \quote {just ignore it}. A \type {+} would
+make the default to always flush the content. This means that at this point we
+only handle:
+
+\starttyping
+<section>
+ <title>Some title</title>
+ <content>
+ <p>a paragraph of text</p>
+ </content>
+</section>
+\stoptyping
+
+In the next section we will deal with the slightly more complex itemize and
+figure placement. At first sight all these setups may look overkill but keep in
+mind that normally the number of elements is rather limited. The complexity is
+often in the style and having access to each snippet of content is actually
+quite handy for that.
+
+\stopsection
+
+\startsection[title={alternative solutions}]
+
+Dealing with an itemize is rather simple (as long as we forget about
+attributes that control the behaviour):
+
+\starttyping
+<itemize>
+ <item>first</item>
+ <item>second</item>
+</itemize>
+\stoptyping
+
+First we need to add \type {itemize} to the setup assignment (unless we've used
+the wildcard \type {*}):
+
+\starttyping
+\xmlsetsetup{demo}{document|section|p|itemize}{xml:demo:*}
+\stoptyping
+
+The setup can look like:
+
+\starttyping
+\startxmlsetups xml:demo:itemize
+ \startitemize
+ \xmlfilter{#1}{/item/command(xml:demo:itemize:item)}
+ \stopitemize
+\stopxmlsetups
+
+\startxmlsetups xml:demo:itemize:item
+ \startitem
+ \xmlflush{#1}
+ \stopitem
+\stopxmlsetups
+\stoptyping
+
+An alternative is to map item directly:
+
+\starttyping
+\xmlsetsetup{demo}{document|section|p|itemize|item}{xml:demo:*}
+\stoptyping
+
+and use:
+
+\starttyping
+\startxmlsetups xml:demo:itemize
+ \startitemize
+ \xmlflush{#1}
+ \stopitemize
+\stopxmlsetups
+
+\startxmlsetups xml:demo:item
+ \startitem
+ \xmlflush{#1}
+ \stopitem
+\stopxmlsetups
+\stoptyping
+
+Sometimes, a more local solution using filters and \type {/command(...)} makes more
+sense, especially when the \type {item} tag is used for other purposes as well.
+
+Explicit flushing with \type {command} is definitely the way to go when you have
+complex products. In one of our projects we compose math school books from many
+thousands of small \XML\ files, and from one source set several products are
+typeset. Within a book sections get done differently, content gets used, ignored
+or interpreted differently depending on the kind of content, so there is a
+constant checking of attributes that drive the rendering. In that a generic setup
+for a title element makes less sense than explicit ones for each case. (We're
+talking of huge amounts of files here, including multiple images on each rendered
+page.)
+
+When using \type {command} you can pass two arguments, the first is the setup for
+the match, the second one for the miss, as in:
+
+\starttyping
+\xmlfilter{#1}{/element/command(xml:true,xml:false)}
+\stoptyping
+
+Back to the example, this leaves us with dealing with the resources, like
+figures:
+
+\starttyping
+<resource type='figure'>
+ <caption>A picture of a cow.</caption>
+ <content><external file="cow.pdf"/></content>
+</resource>
+\stoptyping
+
+Here we can use a more restricted match:
+
+\starttyping
+\xmlsetsetup{demo}{resource[@type='figure']}{xml:demo:figure}
+\xmlsetsetup{demo}{external}{xml:demo:*}
+\stoptyping
+
+and the definitions:
+
+\starttyping
+\startxmlsetups xml:demo:figure
+ \placefigure
+ {\xmlfirst{#1}{/caption}}
+ {\xmlfirst{#1}{/content}}
+\stopxmlsetups
+
+\startxmlsetups xml:demo:external
+ \externalfigure[\xmlatt{#1}{file}]
+\stopxmlsetups
+\stoptyping
+
+At this point it is good to notice that \type {\xmlatt{#1}{file}} is passed as it
+is: a macro call. This means that when a macro like \type {\externalfigure} uses
+the first argument frequently without first storing its value, the lookup is done
+several times. A solution for this is:
+
+\starttyping
+\startxmlsetups xml:demo:external
+ \expanded{\externalfigure[\xmlatt{#1}{file}]}
+\stopxmlsetups
+\stoptyping
+
+Because the lookup is rather fast, normally there is no need to bother about this
+too much because internally \CONTEXT\ already makes sure such expansion happens
+only once.
+
+An alternative definition for placement is the following:
+
+\starttyping
+\xmlsetsetup{demo}{resource}{xml:demo:resource}
+\stoptyping
+
+with:
+
+\starttyping
+\startxmlsetups xml:demo:resource
+ \placefloat
+ [\xmlatt{#1}{type}]
+ {\xmlfirst{#1}{/caption}}
+ {\xmlfirst{#1}{/content}}
+\stopxmlsetups
+\stoptyping
+
+This way you can specify \type {table} as type too. Because you can define your
+own float types, more complex variants are also possible. In that case it makes
+sense to provide some default behaviour too:
+
+\starttyping
+\definefloat[figure-here][figure][default=here]
+\definefloat[figure-left][figure][default=left]
+\definefloat[table-here] [table] [default=here]
+\definefloat[table-left] [table] [default=left]
+
+\startxmlsetups xml:demo:resource
+ \placefloat
+ [\xmlattdef{#1}{type}{figure}-\xmlattdef{#1}{location}{here}]
+ {\xmlfirst{#1}{/caption}}
+ {\xmlfirst{#1}{/content}}
+\stopxmlsetups
+\stoptyping
+
+In this example we support two types and two locations. We default to a figure
+placed (when possible) at the current location.
+
+\stopsection
+
+\stopchapter
+
+\stopcomponent
diff --git a/doc/context/sources/general/manuals/xml/xml-mkiv-examples.tex b/doc/context/sources/general/manuals/xml/xml-mkiv-examples.tex
new file mode 100644
index 000000000..064510d6d
--- /dev/null
+++ b/doc/context/sources/general/manuals/xml/xml-mkiv-examples.tex
@@ -0,0 +1,948 @@
+\environment xml-mkiv-style
+
+\startcomponent xml-mkiv-examples
+
+\startchapter[title=Examples]
+
+\startsection[title=attribute chains]
+
+In \CSS, when an attribute is not present, the parent element is checked, and when
+not found again, the lookup follows the chain till a match is found or the root is
+reached. The following example demonstrates how such a chain lookup works.
+
+\startbuffer[test]
+<something mine="1" test="one" more="alpha">
+ <whatever mine="2" test="two">
+ <whocares mine="3">
+ <!-- this is a test -->
+ </whocares>
+ </whatever>
+</something>
+\stopbuffer
+
+\typebuffer[test]
+
+We apply the following setups to this tree:
+
+\startbuffer[setups]
+\startxmlsetups xml:common
+ [
+ \xmlchainatt{#1}{mine},
+ \xmlchainatt{#1}{test},
+ \xmlchainatt{#1}{more},
+ \xmlchainatt{#1}{none}
+ ]\par
+\stopxmlsetups
+
+\startxmlsetups xml:something
+ something: \xmlsetup{#1}{xml:common}
+ \xmlflush{#1}
+\stopxmlsetups
+
+\startxmlsetups xml:whatever
+ whatever: \xmlsetup{#1}{xml:common}
+ \xmlflush{#1}
+\stopxmlsetups
+
+\startxmlsetups xml:whocares
+ whocares: \xmlsetup{#1}{xml:common}
+ \xmlflush{#1}
+\stopxmlsetups
+
+\startxmlsetups xml:mysetups
+ \xmlsetsetup{#1}{something|whatever|whocares}{xml:*}
+\stopxmlsetups
+
+\xmlregisterdocumentsetup{example-1}{xml:mysetups}
+
+\xmlprocessbuffer{example-1}{test}{}
+\stopbuffer
+
+\typebuffer[setups]
+
+This gives:
+
+\start
+ \getbuffer[setups]
+\stop
+
+\stopsection
+
+\startsection[title=conditional setups]
+
+Say that we have this code:
+
+\starttyping
+\xmldoifelse {#1} {/what[@a='1']} {
+ \xmlfilter {#1} {/what/command('xml:yes')}
+} {
+ \xmlfilter {#1} {/what/command('xml:nop')}
+}
+\stoptyping
+
+Here we first determine if there is a child \type {what} with attribute \type {a}
+set to \type {1}. Depending on the outcome again we check the child nodes for
+being named \type {what}. A faster solution which also takes less code is this:
+
+\starttyping
+\xmlfilter {#1} {/what[@a='1']/command('xml:yes','xml:nop')}
+\stoptyping
+
+\stopsection
+
+\startsection[title=manipulating]
+
+Assume that we have the following \XML\ data:
+
+\startbuffer[test]
+<A>
+ <B>right</B>
+ <B>wrong</B>
+</A>
+\stopbuffer
+
+\typebuffer[test]
+
+But, instead of \type {right} we want to see \type {okay}. We can do that with a
+finalizer:
+
+\startbuffer
+\startluacode
+local rehash = {
+ ["right"] = "okay",
+}
+
+function xml.finalizers.tex.Okayed(collected,what)
+ for i=1,#collected do
+ if what == "all" then
+ local str = xml.text(collected[i])
+ context(rehash[str] or str)
+ else
+ context(str)
+ end
+ end
+end
+\stopluacode
+\stopbuffer
+
+\typebuffer \getbuffer
+
+\startbuffer
+\startxmlsetups xml:A
+ \xmlflush{#1}
+\stopxmlsetups
+
+\startxmlsetups xml:B
+ (It's \xmlfilter{#1}{./Okayed("all")})
+\stopxmlsetups
+
+\startxmlsetups xml:testsetups
+ \xmlsetsetup{#1}{A|B}{xml:*}
+\stopxmlsetups
+
+\xmlregisterdocumentsetup{example-2}{xml:testsetups}
+\xmlprocessbuffer{example-2}{test}{}
+\stopbuffer
+
+\typebuffer
+
+The result is: \start \inlinebuffer \stop
+
+\stopsection
+
+\startsection[title=cross referencing]
+
+A rather common way to add cross references to \XML\ files is to borrow the
+asymmetrical id's from \HTML. This means that one cannot simply use a value
+of (say) \type {href} to locate an \type {id}. The next example came up on
+the \CONTEXT\ mailing list.
+
+\startbuffer[test]
+<doc>
+ <p>Text
+ <a href="#fn1" class="footnoteref" id="fnref1"><sup>1</sup></a> and
+ <a href="#fn2" class="footnoteref" id="fnref2"><sup>2</sup></a>
+ </p>
+ <div class="footnotes">
+ <hr />
+ <ol>
+ <li id="fn1"><p>A footnote.<a href="#fnref1">↩</a></p></li>
+ <li id="fn2"><p>A second footnote.<a href="#fnref2">↩</a></p></li>
+ </ol>
+ </div>
+</doc>
+\stopbuffer
+
+\typebuffer[test]
+
+We give two variants for dealing with such references. The first solution does
+lookups and depending on the size of the file can be somewhat inefficient.
+
+\startbuffer
+\startxmlsetups xml:doc
+ \blank
+ \xmlflush{#1}
+ \blank
+\stopxmlsetups
+
+\startxmlsetups xml:p
+ \xmlflush{#1}
+\stopxmlsetups
+
+\startxmlsetups xml:footnote
+ (variant 1)\footnote
+ {\xmlfirst
+ {example-3-1}
+ {div[@class='footnotes']/ol/li[@id='\xmlrefatt{#1}{href}']}}
+\stopxmlsetups
+
+\startxmlsetups xml:initialize
+ \xmlsetsetup{#1}{p|doc}{xml:*}
+ \xmlsetsetup{#1}{a[@class='footnoteref']}{xml:footnote}
+ \xmlsetsetup{#1}{div[@class='footnotes']}{xml:nothing}
+\stopxmlsetups
+
+\xmlresetdocumentsetups{*}
+\xmlregisterdocumentsetup{example-3-1}{xml:initialize}
+
+\xmlprocessbuffer{example-3-1}{test}{}
+\stopbuffer
+
+\typebuffer
+
+This will typeset two footnotes.
+
+\getbuffer
+
+The second variant collects the references so that the time spend on lookups is
+less.
+
+\startbuffer
+\startxmlsetups xml:doc
+ \blank
+ \xmlflush{#1}
+ \blank
+\stopxmlsetups
+
+\startxmlsetups xml:p
+ \xmlflush{#1}
+\stopxmlsetups
+
+\startluacode
+ userdata.notes = {}
+\stopluacode
+
+\startxmlsetups xml:collectnotes
+ \ctxlua{userdata.notes['\xmlrefatt{#1}{id}'] = '#1'}
+\stopxmlsetups
+
+\startxmlsetups xml:footnote
+ (variant 2)\footnote
+ {\xmlflush
+ {\cldcontext{userdata.notes['\xmlrefatt{#1}{href}']}}}
+\stopxmlsetups
+
+\startxmlsetups xml:initialize
+ \xmlsetsetup{#1}{p|doc}{xml:*}
+ \xmlsetsetup{#1}{a[@class='footnoteref']}{xml:footnote}
+ \xmlfilter{#1}{div[@class='footnotes']/ol/li/command(xml:collectnotes)}
+ \xmlsetsetup{#1}{div[@class='footnotes']}{}
+\stopxmlsetups
+
+\xmlregisterdocumentsetup{example-3-2}{xml:initialize}
+
+\xmlprocessbuffer{example-3-2}{test}{}
+\stopbuffer
+
+\typebuffer
+
+This will again typeset two footnotes:
+
+\getbuffer
+
+\stopsection
+
+\startsection[title=mapping values]
+
+One way to process options \type {frame} in the example below is to map the
+values to values known by \CONTEXT.
+
+\startbuffer[test]
+<a>
+ <nattable frame="on">
+ <tr><td>#1</td><td>#2</td><td>#3</td><td>#4</td></tr>
+ <tr><td>#5</td><td>#6</td><td>#7</td><td>#8</td></tr>
+ </nattable>
+ <nattable frame="off">
+ <tr><td>#1</td><td>#2</td><td>#3</td><td>#4</td></tr>
+ <tr><td>#5</td><td>#6</td><td>#7</td><td>#8</td></tr>
+ </nattable>
+ <nattable frame="no">
+ <tr><td>#1</td><td>#2</td><td>#3</td><td>#4</td></tr>
+ <tr><td>#5</td><td>#6</td><td>#7</td><td>#8</td></tr>
+ </nattable>
+</a>
+\stopbuffer
+
+\typebuffer[test]
+
+\startbuffer
+\startxmlsetups xml:a
+ \xmlflush{#1}
+\stopxmlsetups
+
+\xmlmapvalue {nattable:frame} {on} {on}
+\xmlmapvalue {nattable:frame} {yes} {on}
+\xmlmapvalue {nattable:frame} {off} {off}
+\xmlmapvalue {nattable:frame} {no} {off}
+
+\startxmlsetups xml:nattable
+ \startplacetable[title=#1]
+ \setupTABLE[frame=\xmlval{nattable:frame}{\xmlatt{#1}{frame}}{on}]%
+ \bTABLE
+ \xmlflush{#1}
+ \eTABLE
+ \stopplacetable
+\stopxmlsetups
+
+\startxmlsetups xml:tr
+ \bTR
+ \xmlflush{#1}
+ \eTR
+\stopxmlsetups
+
+\startxmlsetups xml:td
+ \bTD
+ \xmlflush{#1}
+ \eTD
+\stopxmlsetups
+
+\startxmlsetups xml:testsetups
+ \xmlsetsetup{example-4}{a|nattable|tr|td|}{xml:*}
+\stopxmlsetups
+
+\xmlregisterdocumentsetup{example-4}{xml:testsetups}
+
+\xmlprocessbuffer{example-4}{test}{}
+\stopbuffer
+
+The \type {\xmlmapvalue} mechanism is rather efficient and involves a minimum
+of testing.
+
+\typebuffer
+
+We get:
+
+\getbuffer
+
+\stopsection
+
+\startsection[title=using \LUA]
+
+In this example we demonstrate how you can delegate rendering to \LUA. We
+will construct a so called extreme table. The input is:
+
+\startbuffer[demo]
+<?xml version="1.0" encoding="utf-8"?>
+
+<a>
+ <b> <c>1</c> <d>Text</d> </b>
+ <b> <c>2</c> <d>More text</d> </b>
+ <b> <c>2</c> <d>Even more text</d> </b>
+ <b> <c>2</c> <d>And more</d> </b>
+ <b> <c>3</c> <d>And even more</d> </b>
+ <b> <c>2</c> <d>The last text</d> </b>
+</a>
+\stopbuffer
+
+\typebuffer[demo]
+
+The processor code is:
+
+\startbuffer[process]
+\startxmlsetups xml:test_setups
+ \xmlsetsetup{#1}{a|b|c|d}{xml:*}
+\stopxmlsetups
+
+\xmlregisterdocumentsetup{example-5}{xml:test_setups}
+
+\xmlprocessbuffer{example-5}{demo}{}
+\stopbuffer
+
+\typebuffer
+
+We color a sequence of the same titles (numbers here) differently. The first
+solution remembers the last title:
+
+\startbuffer
+\startxmlsetups xml:a
+ \startembeddedxtable
+ \xmlflush{#1}
+ \stopembeddedxtable
+\stopxmlsetups
+
+\startxmlsetups xml:b
+ \xmlfunction{#1}{test_ba}
+\stopxmlsetups
+
+\startluacode
+local lasttitle = nil
+
+function xml.functions.test_ba(t)
+ local title = xml.text(t, "/c")
+ local content = xml.text(t, "/d")
+ context.startxrow()
+ context.startxcell {
+ background = "color",
+ backgroundcolor = lasttitle == title and "colorone" or "colortwo",
+ foregroundstyle = "bold",
+ foregroundcolor = "white",
+ }
+ context(title)
+ lasttitle = title
+ context.stopxcell()
+ context.startxcell()
+ context(content)
+ context.stopxcell()
+ context.stopxrow()
+end
+\stopluacode
+\stopbuffer
+
+\typebuffer \getbuffer
+
+The \type {embeddedxtable} environment is needed because the table is picked up
+as argument.
+
+\startlinecorrection \getbuffer[process] \stoplinecorrection
+
+The second implemetation remembers what titles are already processed so here we
+can color the last one too.
+
+\startbuffer
+\startxmlsetups xml:a
+ \ctxlua{xml.functions.reset_bb()}
+ \startembeddedxtable
+ \xmlflush{#1}
+ \stopembeddedxtable
+\stopxmlsetups
+
+\startxmlsetups xml:b
+ \xmlfunction{#1}{test_bb}
+\stopxmlsetups
+
+\startluacode
+local titles
+
+function xml.functions.reset_bb(t)
+ titles = { }
+end
+
+function xml.functions.test_bb(t)
+ local title = xml.text(t, "/c")
+ local content = xml.text(t, "/d")
+ context.startxrow()
+ context.startxcell {
+ background = "color",
+ backgroundcolor = titles[title] and "colorone" or "colortwo",
+ foregroundstyle = "bold",
+ foregroundcolor = "white",
+ }
+ context(title)
+ titles[title] = true
+ context.stopxcell()
+ context.startxcell()
+ context(content)
+ context.stopxcell()
+ context.stopxrow()
+end
+\stopluacode
+\stopbuffer
+
+\typebuffer \getbuffer
+
+\startlinecorrection \getbuffer[process] \stoplinecorrection
+
+A solution without any state variable is given below.
+
+\startbuffer
+\startxmlsetups xml:a
+ \startembeddedxtable
+ \xmlflush{#1}
+ \stopembeddedxtable
+\stopxmlsetups
+
+\startxmlsetups xml:b
+ \xmlfunction{#1}{test_bc}
+\stopxmlsetups
+
+\startluacode
+function xml.functions.test_bc(t)
+ local title = xml.text(t, "/c")
+ local content = xml.text(t, "/d")
+ context.startxrow()
+ local okay = xml.text(t,"./preceding-sibling::/[-1]") == title
+ context.startxcell {
+ background = "color",
+ backgroundcolor = okay and "colorone" or "colortwo",
+ foregroundstyle = "bold",
+ foregroundcolor = "white",
+ }
+ context(title)
+ context.stopxcell()
+ context.startxcell()
+ context(content)
+ context.stopxcell()
+ context.stopxrow()
+end
+\stopluacode
+\stopbuffer
+
+\typebuffer \getbuffer
+
+\startlinecorrection \getbuffer[process] \stoplinecorrection
+
+Here is a solution that delegates even more to \LUA. The previous variants were
+actually not that safe with repect to special characters and didn't handle
+nested elements either but the next one does.
+
+\startbuffer[demo]
+<?xml version="1.0" encoding="utf-8"?>
+
+<a>
+ <b> <c>#1</c> <d>Text</d> </b>
+ <b> <c>#2</c> <d>More text</d> </b>
+ <b> <c>#2</c> <d>Even more text</d> </b>
+ <b> <c>#2</c> <d>And more</d> </b>
+ <b> <c>#3</c> <d>And even more</d> </b>
+ <b> <c>#2</c> <d>Something <i>nested</i> </d> </b>
+</a>
+\stopbuffer
+
+\typebuffer[demo]
+
+We also need to map the \type {i} element.
+
+\startbuffer
+\startxmlsetups xml:a
+ \starttexcode
+ \xmlfunction{#1}{test_a}
+ \stoptexcode
+\stopxmlsetups
+
+\startxmlsetups xml:c
+ \xmlflush{#1}
+\stopxmlsetups
+
+\startxmlsetups xml:d
+ \xmlflush{#1}
+\stopxmlsetups
+
+\startxmlsetups xml:i
+ {\em\xmlflush{#1}}
+\stopxmlsetups
+
+\startluacode
+function xml.functions.test_a(t)
+ context.startxtable()
+ local previous = false
+ for b in xml.collected(lxml.getid(t),"/b") do
+ context.startxrow()
+ local current = xml.text(b,"/c")
+ context.startxcell {
+ background = "color",
+ backgroundcolor = (previous == current) and "colorone" or "colortwo",
+ foregroundstyle = "bold",
+ foregroundcolor = "white",
+ }
+ lxml.first(b,"/c")
+ context.stopxcell()
+ context.startxcell()
+ lxml.first(b,"/d")
+ context.stopxcell()
+ previous = current
+ context.stopxrow()
+ end
+ context.stopxtable()
+end
+\stopluacode
+
+\startxmlsetups xml:test_setups
+ \xmlsetsetup{#1}{a|b|c|d|i}{xml:*}
+\stopxmlsetups
+
+\xmlregisterdocumentsetup{example-5}{xml:test_setups}
+
+\xmlprocessbuffer{example-5}{demo}{}
+\stopbuffer
+
+\typebuffer
+
+\startlinecorrection \getbuffer \stoplinecorrection
+
+The question is, do we really need \LUA ? Often we don't, apart maybe from an
+occasional special finalizer. A pure \TEX\ solution is given next:
+
+\startbuffer
+\startxmlsetups xml:a
+ \glet\MyPreviousTitle\empty
+ \glet\MyCurrentTitle \empty
+ \startembeddedxtable
+ \xmlflush{#1}
+ \stopembeddedxtable
+\stopxmlsetups
+
+\startxmlsetups xml:b
+ \startxrow
+ \xmlflush{#1}
+ \stopxrow
+\stopxmlsetups
+
+\startxmlsetups xml:c
+ \xdef\MyCurrentTitle{\xmltext{#1}{.}}
+ \doifelse {\MyPreviousTitle} {\MyCurrentTitle} {
+ \startxcell
+ [background=color,
+ backgroundcolor=colorone,
+ foregroundstyle=bold,
+ foregroundcolor=white]
+ } {
+ \glet\MyPreviousTitle\MyCurrentTitle
+ \startxcell
+ [background=color,
+ backgroundcolor=colortwo,
+ foregroundstyle=bold,
+ foregroundcolor=white]
+ }
+ \xmlflush{#1}
+ \stopxcell
+\stopxmlsetups
+
+\startxmlsetups xml:d
+ \startxcell
+ \xmlflush{#1}
+ \stopxcell
+\stopxmlsetups
+
+\startxmlsetups xml:i
+ {\em\xmlflush{#1}}
+\stopxmlsetups
+
+\startxmlsetups xml:test_setups
+ \xmlsetsetup{#1}{*}{xml:*}
+\stopxmlsetups
+
+\xmlregisterdocumentsetup{example-5}{xml:test_setups}
+
+\xmlprocessbuffer{example-5}{demo}{}
+\stopbuffer
+
+\typebuffer
+
+\startlinecorrection \getbuffer \stoplinecorrection
+
+You can even save a few lines of code:
+
+\starttyping
+\startxmlsetups xml:c
+ \xdef\MyCurrentTitle{\xmltext{#1}{.}}
+ \startxcell
+ [background=color,
+ backgroundcolor=color\ifx\MyPreviousTitle\MyCurrentTitle one\else two\fi,
+ foregroundstyle=bold,
+ foregroundcolor=white]
+ \xmlflush{#1}
+ \stopxcell
+ \glet\MyPreviousTitle\MyCurrentTitle
+\stopxmlsetups
+\stoptyping
+
+Or if you prefer:
+
+\starttyping
+\startxmlsetups xml:c
+ \xdef\MyCurrentTitle{\xmltext{#1}{.}}
+ \doifelse {\MyPreviousTitle} {\MyCurrentTitle} {
+ \xmlsetup{#1}{xml:c:one}
+ } {
+ \xmlsetup{#1}{xml:c:two}
+ }
+\stopxmlsetups
+
+\startxmlsetups xml:c:one
+ \startxcell
+ [background=color,
+ backgroundcolor=colorone,
+ foregroundstyle=bold,
+ foregroundcolor=white]
+ \xmlflush{#1}
+ \stopxcell
+\stopxmlsetups
+
+\startxmlsetups xml:c:two
+ \startxcell
+ [background=color,
+ backgroundcolor=colortwo,
+ foregroundstyle=bold,
+ foregroundcolor=white]
+ \xmlflush{#1}
+ \stopxcell
+ \global\let\MyPreviousTitle\MyCurrentTitle
+\stopxmlsetups
+\stoptyping
+
+These examples demonstrate that it doesn't hurt to know a little bit of \TEX\
+programming: defining macros and basic comparisons can come in handy. There are
+examples in the test suite, you can peek in the source code, you can consult
+the wiki or you can just ask on the list.
+
+\stopsection
+
+\startsection[title=last match]
+
+For the next example we use the following \XML\ input:
+
+\startbuffer[demo]
+<?xml version "1.0"?>
+<document>
+ <section id="1">
+ <content>
+ <p>first</p>
+ <p>second</p>
+ </content>
+ </section>
+ <section id="2">
+ <content>
+ <p>third</p>
+ <p>fourth</p>
+ </content>
+ </section>
+</document>
+\stopbuffer
+
+\typebuffer[demo]
+
+If you check if some element is present and then act accordingly, you can
+end up with doing the same lookup twice. Although it might sound inefficient,
+in practice it's often not measureable.
+
+\startbuffer
+\startxmlsetups xml:demo:document
+ \type{\xmlall{#1}{/section[@id='2']/content/p}}\par
+ \xmldoif{#1}{/section[@id='2']/content/p} {
+ \xmlall{#1}{/section[@id='2']/content/p}
+ }
+ \type{\xmllastmatch}\par
+ \xmldoif{#1}{/section[@id='2']/content/p} {
+ \xmllastmatch
+ }
+ \type{\xmlall{#1}{last-match::}}\par
+ \xmldoif{#1}{/section[@id='2']/content/p} {
+ \xmlall{#1}{last-match::}
+ }
+ \type{\xmlfilter{#1}{last-match::/command(xml:demo:p)}}\par
+ \xmldoif{#1}{/section[@id='2']/content/p} {
+ \xmlfilter{#1}{last-match::/command(xml:demo:p)}
+ }
+\stopxmlsetups
+
+\startxmlsetups xml:demo:p
+ \quad\xmlflush{#1}\endgraf
+\stopxmlsetups
+
+\startxmlsetups xml:demo:base
+ \xmlsetsetup{#1}{document|p}{xml:demo:*}
+\stopxmlsetups
+
+\xmlregisterdocumentsetup{example-6}{xml:demo:base}
+
+\xmlprocessbuffer{example-6}{demo}{}
+\stopbuffer
+
+\typebuffer
+
+In the second check we just flush the last match, so effective we do an \type
+{\xmlall} here. The third and fourth alternatives demonstrate how we can use
+\type {last-match} as axis. The gain is 10\% or more on the lookup but of course
+typesetting often takes relatively more time than the lookup.
+
+\startpacked
+\getbuffer
+\stoppacked
+
+\stopsection
+
+\startsection[title=Finalizers]
+
+The \XML\ parser is also available outside \TEX. Here is an example of its usage.
+We pipe the result to \TEX\ but you can do with \type {t} whatever you like.
+
+\startbuffer
+local x = xml.load("manual-demo-1.xml")
+local t = { }
+
+for c in xml.collected(x,"//*") do
+ if not c.special and not t[c.tg] then
+ t[c.tg] = true
+ end
+end
+
+context.tocontext(table.sortedkeys(t))
+\stopbuffer
+
+% \typebuffer
+
+This returns:
+
+\ctxluabuffer
+
+We can wrap this in a finalizer:
+
+\startbuffer
+xml.finalizers.taglist = function(collected)
+ local t = { }
+ for i=1,#collected do
+ local c = collected[i]
+ if not c.special then
+ local tg = c.tg
+ if tg and not t[tg] then
+ t[tg] = true
+ end
+ end
+ end
+ return table.sortedkeys(t)
+end
+\stopbuffer
+
+\typebuffer
+
+Or in a more extensive one:
+
+\startbuffer
+xml.finalizers.taglist = function(collected,parenttoo)
+ local t = { }
+ for i=1,#collected do
+ local c = collected[i]
+ if not c.special then
+ local tg = c.tg
+ if tg and not t[tg] then
+ t[tg] = true
+ end
+ if parenttoo then
+ local p = c.__p__
+ if p and not p.special then
+ local tg = p.tg .. ":" .. tg
+ if tg and not t[tg] then
+ t[tg] = true
+ end
+ end
+ end
+ end
+ end
+ return table.sortedkeys(t)
+end
+\stopbuffer
+
+\typebuffer \ctxluabuffer
+
+Usage is as follows:
+
+\startbuffer
+local x = xml.load("manual-demo-1.xml")
+local t = xml.applylpath(x,"//*/taglist()")
+
+context.tocontext(t)
+\stopbuffer
+
+\typebuffer
+
+And indeed we get:
+
+\ctxluabuffer
+
+But we can also say:
+
+\startbuffer
+local x = xml.load("manual-demo-1.xml")
+local t = xml.applylpath(x,"//*/taglist(true)")
+
+context.tocontext(t)
+\stopbuffer
+
+\typebuffer
+
+Now we get:
+
+\ctxluabuffer
+
+\stopsection
+
+\startsection[title=Pure xml]
+
+One might wonder how a \TEX\ macro package would look like when backslashes,
+dollars and percent signs would have no special meaning. In fact, it would be
+rather useless as interpreting commands are triggered by such characters. Any
+formatting or coding system needs such characters. Take \XML: angle brackets and
+ampersands are really special. So, no matter what system we use, we do have to
+deal with the (common) case where these characters need to be seen as they are.
+Normally escaping is the solution.
+
+The \CONTEXT\ interface for \XML\ suffers from this as well. You really don't
+want to know how many tricks are used for dealing with special characters and
+entities: there are several ways these travel through the system and it is
+possible to adapt and cheat. Especially roundtripped data (via tuc file) puts
+some demands on the system because when ts \XML\ can become \TEX\ and vise versa.
+The next example (derived from a mail on the list) demonstrates this:
+
+\starttyping
+\startbuffer[demo]
+<doc>
+ <pre><code>\ConTeXt\ is great</code></pre>
+
+ <pre><code>but you need to know some tricks</code></pre>
+</doc>
+\stopbuffer
+
+\startxmlsetups xml:initialize
+ \xmlsetsetup{#1}{doc|p|code}{xml:*}
+ \xmlsetsetup{#1}{pre/code}{xml:pre:code}
+\stopxmlsetups
+
+\xmlregistersetup{xml:initialize}
+
+\startxmlsetups xml:doc
+ \xmlflush{#1}
+\stopxmlsetups
+
+\startxmlsetups xml:pre:code
+ no solution
+ \comment[symbol=Key, location=inmargin,color=yellow]{\xmlflush{#1}}
+ \par
+ solution one \begingroup
+ \expandUx
+ \comment[symbol=Key, location=inmargin,color=yellow]{\xmlflush{#1}}
+ \endgroup
+ \par
+ solution two
+ \comment[symbol=Key, location=inmargin,color=yellow]{\xmlpure{#1}}
+ \par
+ \xmlprettyprint{#1}{tex}
+\stopxmlsetups
+
+\xmlprocessbuffer{main}{demo}{}
+\stoptyping
+
+The first comment (an interactive feature of \PDF\ comes out as:
+
+\starttyping
+\Ux {5C}ConTeXt\Ux {5C} is great
+\stoptyping
+
+The second and third comment are okay. It's one of the reasons why we have \type
+{\xmlpure}.
+
+\stopsection
+
+\stopchapter
+
+\stopcomponent
diff --git a/doc/context/sources/general/manuals/xml/xml-mkiv-expressions.tex b/doc/context/sources/general/manuals/xml/xml-mkiv-expressions.tex
new file mode 100644
index 000000000..0c126f2f8
--- /dev/null
+++ b/doc/context/sources/general/manuals/xml/xml-mkiv-expressions.tex
@@ -0,0 +1,645 @@
+\environment xml-mkiv-style
+
+\startcomponent xml-mkiv-expressions
+
+\startchapter[title={Expressions and filters}]
+
+\startsection[title={path expressions}]
+
+In the previous chapters we used \cmdinternal {cd:lpath} expressions, which are a variant
+on \type {xpath} expressions as in \XSLT\ but in this case more geared towards
+usage in \TEX. This mechanisms will be extended when demands are there.
+
+A path is a sequence of matches. A simple path expression is:
+
+\starttyping
+a/b/c/d
+\stoptyping
+
+Here each \type {/} goes one level deeper. We can go backwards in a lookup with
+\type {..}:
+
+\starttyping
+a/b/../d
+\stoptyping
+
+We can also combine lookups, as in:
+
+\starttyping
+a/(b|c)/d
+\stoptyping
+
+A negated lookup is preceded by a \type {!}:
+
+\starttyping
+a/(b|c)/!d
+\stoptyping
+
+A wildcard is specified with a \type {*}:
+
+\starttyping
+a/(b|c)/!d/e/*/f
+\stoptyping
+
+In addition to these tag based lookups we can use attributes:
+
+\starttyping
+a/(b|c)/!d/e/*/f[@type=whatever]
+\stoptyping
+
+An \type {@} as first character means that we are dealing with an attribute.
+Within the square brackets there can be boolean expressions:
+
+\starttyping
+a/(b|c)/!d/e/*/f[@type=whatever and @id>100]
+\stoptyping
+
+You can use functions as in:
+
+\starttyping
+a/(b|c)/!d/e/*/f[something(text()) == "oeps"]
+\stoptyping
+
+There are a couple of predefined functions:
+
+\starttabulate[|l|l|p|]
+\NC \type{rootposition} \type{order} \NC number \NC the index of the matched root element (kind of special) \NC \NR
+\NC \type{position} \NC number \NC the current index of the matched element in the match list \NC \NR
+\NC \type{match} \NC number \NC the current index of the matched element sub list with the same parent \NC \NR
+\NC \type{first} \NC number \NC \NC \NR
+\NC \type{last} \NC number \NC \NC \NR
+\NC \type{index} \NC number \NC the current index of the matched element in its parent list \NC \NR
+\NC \type{firstindex} \NC number \NC \NC \NR
+\NC \type{lastindex} \NC number \NC \NC \NR
+\NC \type{element} \NC number \NC the element's index \NC \NR
+\NC \type{firstelement} \NC number \NC \NC \NR
+\NC \type{lastelement} \NC number \NC \NC \NR
+\NC \type{text} \NC string \NC the textual representation of the matched element \NC \NR
+\NC \type{content} \NC table \NC the node of the matched element \NC \NR
+\NC \type{name} \NC string \NC the full name of the matched element: namespace and tag \NC \NR
+\NC \type{namespace} \type{ns} \NC string \NC the namespace of the matched element \NC \NR
+\NC \type{tag} \NC string \NC the tag of the matched element \NC \NR
+\NC \type{attribute} \NC string \NC the value of the attribute with the given name of the matched element \NC \NR
+\stoptabulate
+
+There are fundamental differences between \type {position}, \type {match} and
+\type {index}. Each step results in a new list of matches. The \type {position}
+is the index in this new (possibly intermediate) list. The \type {match} is also
+an index in this list but related to the specific match of element names. The
+\type {index} refers to the location in the parent element.
+
+Say that we have:
+
+\starttyping
+<collection>
+ <resources>
+ <manual>
+ <screen>.1.</screen>
+ <paper>.1.</paper>
+ </manual>
+ <manual>
+ <paper>.2.</paper>
+ <screen>.2.</screen>
+ </manual>
+ <resources>
+ <resources>
+ <manual>
+ <screen>.3.</screen>
+ <paper>.3.</paper>
+ </manual>
+ <resources>
+<collection>
+\stoptyping
+
+The following then applies:
+
+\starttabulate[|l|l|]
+\NC \type {collection/resources/manual[position()==1]/paper} \NC \type{.1.} \NC \NR
+\NC \type {collection/resources/manual[match()==1]/paper} \NC \type{.1.} \type{.3.} \NC \NR
+\NC \type {collection/resources/manual/paper[index()==1]} \NC \type{.2.} \NC \NR
+\stoptabulate
+
+In most cases the \type {position} test is more restrictive than the \type
+{match} test.
+
+You can pass your own functions too. Such functions are defined in the \type
+{xml.expressions} namespace. We have defined a few shortcuts:
+
+\starttabulate[|l|l|]
+\NC \type {find(str,pattern)} \NC \type{string.find} \NC \NR
+\NC \type {contains(str)} \NC \type{string.find} \NC \NR
+\NC \type {oneof(str,...)} \NC is \type{str} in list \NC \NR
+\NC \type {upper(str)} \NC \type{characters.upper} \NC \NR
+\NC \type {lower(str)} \NC \type{characters.lower} \NC \NR
+\NC \type {number(str)} \NC \type{tonumber} \NC \NR
+\NC \type {boolean(str)} \NC \type{toboolean} \NC \NR
+\NC \type {idstring(str)} \NC removes leading hash \NC \NR
+\NC \type {name(index)} \NC full tag name \NC \NR
+\NC \type {tag(index)} \NC tag name \NC \NR
+\NC \type {namespace(index)} \NC namespace of tag \NC \NR
+\NC \type {text(index)} \NC content \NC \NR
+\NC \type {error(str)} \NC quit and show error \NC \NR
+\NC \type {quit()} \NC quit \NC \NR
+\NC \type {print()} \NC print message \NC \NR
+\NC \type {count(pattern)} \NC number of matches \NC \NR
+\NC \type {child(pattern)} \NC take child that matches \NC \NR
+\stoptabulate
+
+
+You can also use normal \LUA\ functions as long as you make sure that you pass
+the right arguments. There are a few predefined variables available inside such
+functions.
+
+\starttabulate[|Tl|l|p|]
+\NC \type{list} \NC table \NC the list of matches \NC \NR
+\NC \type{l} \NC number \NC the current index in the list of matches \NC \NR
+\NC \type{ll} \NC element \NC the current element that matched \NC \NR
+\NC \type{order} \NC number \NC the position of the root of the path \NC \NR
+\stoptabulate
+
+The given expression between \type {[]} is converted to a \LUA\ expression so you
+can use the usual operators:
+
+\starttyping
+== ~= <= >= < > not and or ()
+\stoptyping
+
+In addition, \type {=} equals \type {==} and \type {!=} is the same as \type
+{~=}. If you mess up the expression, you quite likely get a \LUA\ error message.
+
+\stopsection
+
+\startsection[title={css selectors}]
+
+\startbuffer[selector-001]
+<?xml version="1.0" ?>
+
+<a>
+ <b class="one">b.one</b>
+ <b class="two">b.two</b>
+ <b class="one two">b.one.two</b>
+ <b class="three">b.three</b>
+ <b id="first">b#first</b>
+ <c>c</c>
+ <d>d e</d>
+ <e>d e</e>
+ <e>d e e</e>
+ <d>d f</d>
+ <f foo="bar">@foo = bar</f>
+ <f bar="foo">@bar = foo</f>
+ <f bar="foo1">@bar = foo1</f>
+ <f bar="foo2">@bar = foo2</f>
+ <f bar="foo3">@bar = foo3</f>
+ <f bar="foo+4">@bar = foo+4</f>
+ <g>g</g>
+ <g><gg><d>g gg d</d></gg></g>
+ <g><gg><f>g gg f</f></gg></g>
+ <g><gg><f class="one">g gg f.one</f></gg></g>
+ <g>g</g>
+ <g><gg><f class="two">g gg f.two</f></gg></g>
+ <g><gg><f class="three">g gg f.three</f></gg></g>
+ <g><f class="one">g f.one</f></g>
+ <g><f class="three">g f.three</f></g>
+ <h whatever="four five six">@whatever = four five six</h>
+</a>
+\stopbuffer
+
+\xmlloadbuffer{selector-001}{selector-001}
+
+\startxmlsetups xml:selector:demo
+ \advance\scratchcounter\plusone
+ \inleftmargin{\the\scratchcounter}\ignorespaces\xmlverbatim{#1}\par
+\stopxmlsetups
+
+\unexpanded\def\showCSSdemo#1#2%
+ {\blank
+ \textrule{\tttf#2}
+ \startlines
+ \dontcomplain
+ \tttf \obeyspaces
+ \scratchcounter\zerocount
+ \xmlcommand{#1}{#2}{xml:selector:demo}
+ \stoplines
+ \blank}
+
+The \CSS\ approach to filtering is a bit different from the path based one and is
+supported too. In fact, you can combine both methods. Depending on what you
+select, the \CSS\ one can be a little bit faster too. It has the advantage that
+one can select more in one go but at the same time looks a bit less attractive.
+This method was added just to show that it can be done but might be useful too. A
+selector is given between curly braces (after all \CSS\ uses them and they have no
+function yet in the parser.
+
+\starttyping
+\xmlall{#1}{{foo bar .whatever, bar foo .whatever}}
+\stoptyping
+
+The following methods are supported:
+
+\starttabulate[|T||]
+\NC element \NC all tags element \NC \NR
+\NC element-1 > element-2 \NC all tags element-2 with parent tag element-1 \NC \NR
+\NC element-1 + element-2 \NC all tags element-2 preceded by tag element-1 \NC \NR
+\NC element-1 ~ element-2 \NC all tags element-2 preceded by tag element-1 \NC \NR
+\NC element-1 element-2 \NC all tags element-2 inside tag element-1 \NC \NR
+\NC [attribute] \NC has attribute \NC \NR
+\NC [attribute=value] \NC attribute equals value\NC \NR
+\NC [attribute\lettertilde =value] \NC attribute contains value (space is separator) \NC \NR
+\NC [attribute\letterhat ="value"] \NC attribute starts with value \NC \NR
+\NC [attribute\letterdollar="value"] \NC attribute ends with value \NC \NR
+\NC [attribute*="value"] \NC attribute contains value \NC \NR
+\NC .class \NC has class \NC \NR
+\NC \letterhash id \NC has id \NC \NR
+\NC :nth-child(n) \NC the child at index n \NC \NR
+\NC :nth-last-child(n) \NC the child at index n from the end \NC \NR
+\NC :first-child \NC the first child \NC \NR
+\NC :last-child \NC the last child \NC \NR
+\NC :nth-of-type(n) \NC the match at index n \NC \NR
+\NC :nth-last-of-type(n) \NC the match at index n from the end \NC \NR
+\NC :first-of-type \NC the first match \NC \NR
+\NC :last-of-type \NC the last match \NC \NR
+\NC :only-of-type \NC the only match or nothing \NC \NR
+\NC :only-child \NC the only child or nothing \NC \NR
+\NC :empty \NC only when empty \NC \NR
+\NC :root \NC the whole tree \NC \NR
+\stoptabulate
+
+The next pages show some examples. For that we use the demo file:
+
+\typebuffer[selector-001]
+
+The class and id selectors often only make sense in \HTML\ like documents but they
+are supported nevertheless. They are after all just shortcuts for filtering by
+attribute. The class filtering is special in the sense that it checks for a class
+in a list of classes given in an attribute.
+
+\showCSSdemo{selector-001}{{.one}}
+\showCSSdemo{selector-001}{{.one, .two}}
+\showCSSdemo{selector-001}{{.one, .two, \letterhash first}}
+
+Attributes can be filtered by presence, value, partial value and such. Quotes are
+optional but we advice to use them.
+
+\showCSSdemo{selector-001}{{[foo], [bar=foo]}}
+\showCSSdemo{selector-001}{{[bar\lettertilde=foo]}}
+\showCSSdemo{selector-001}{{[bar\letterhat="foo"]}}
+\showCSSdemo{selector-001}{{[whatever\lettertilde="five"]}}
+
+You can of course combine the methods as in:
+
+\showCSSdemo{selector-001}{{g f .one, g f .three}}
+\showCSSdemo{selector-001}{{g > f .one, g > f .three}}
+\showCSSdemo{selector-001}{{d + e}}
+\showCSSdemo{selector-001}{{d ~ e}}
+\showCSSdemo{selector-001}{{d ~ e, g f .one, g f .three}}
+
+You can also negate the result by using \type {:not} on a simple expression:
+
+\showCSSdemo{selector-001}{{:not([whatever\lettertilde="five"])}}
+\showCSSdemo{selector-001}{{:not(d)}}
+
+The child and match selectors are also supported:
+
+\showCSSdemo{selector-001}{{a:nth-child(3)}}
+\showCSSdemo{selector-001}{{a:nth-last-child(3)}}
+\showCSSdemo{selector-001}{{g:nth-of-type(3)}}
+\showCSSdemo{selector-001}{{g:nth-last-of-type(3)}}
+\showCSSdemo{selector-001}{{a:first-child}}
+\showCSSdemo{selector-001}{{a:last-child}}
+\showCSSdemo{selector-001}{{e:first-of-type}}
+\showCSSdemo{selector-001}{{gg d:only-of-type}}
+
+Instead of numbers you can also give the \type {an} and \type {an+b} formulas
+as well as the \type {odd} and \type {even} keywords:
+
+\showCSSdemo{selector-001}{{a:nth-child(even)}}
+\showCSSdemo{selector-001}{{a:nth-child(odd)}}
+\showCSSdemo{selector-001}{{a:nth-child(3n+1)}}
+\showCSSdemo{selector-001}{{a:nth-child(2n+3)}}
+
+There are a few special cases:
+
+\showCSSdemo{selector-001}{{g:empty}}
+\showCSSdemo{selector-001}{{g:root}}
+\showCSSdemo{selector-001}{{*}}
+
+Combining the \CSS\ methods with the regular ones is possible:
+
+\showCSSdemo{selector-001}{{g gg f .one}}
+\showCSSdemo{selector-001}{g/gg/f[@class='one']}
+\showCSSdemo{selector-001}{g/{gg f .one}}
+
+\startbuffer[selector-002]
+<?xml version="1.0" ?>
+
+<document>
+ <title class="one" >title 1</title>
+ <title class="two" >title 2</title>
+ <title class="one" >title 3</title>
+ <title class="three">title 4</title>
+</document>
+\stopbuffer
+
+The next examples we use this file:
+
+\typebuffer[selector-002]
+
+\xmlloadbuffer{selector-002}{selector-002}
+
+When we filter from this (not too well structured) tree we can use both
+methods to achieve the same:
+
+\showCSSdemo{selector-002}{{document title .one, document title .three}}
+
+\showCSSdemo{selector-002}{/document/title[(@class='one') or (@class='three')]}
+
+However, imagine this file:
+
+\startbuffer[selector-003]
+<?xml version="1.0" ?>
+
+<document>
+ <title class="one">title 1</title>
+ <subtitle class="sub">title 1.1</subtitle>
+ <title class="two">title 2</title>
+ <subtitle class="sub">title 2.1</subtitle>
+ <title class="one">title 3</title>
+ <subtitle class="sub">title 3.1</subtitle>
+ <title class="two">title 4</title>
+ <subtitle class="sub">title 4.1</subtitle>
+</document>
+\stopbuffer
+
+\typebuffer[selector-003]
+
+\xmlloadbuffer{selector-003}{selector-003}
+
+The next filter in easier with the \CSS\ selector methods because these accumulate
+independent (simple) expressions:
+
+\showCSSdemo{selector-003}{{document title .one + subtitle, document title .two + subtitle}}
+
+Watch how we get an output in the document order. Because we render a sequential document
+a combined filter will trigger a sorting pass.
+
+\stopsection
+
+\startsection[title={functions as filters}]
+
+At the \LUA\ end a whole \cmdinternal {cd:lpath} expression results in a (set of) node(s)
+with its environment, but that is hardly usable in \TEX. Think of code like:
+
+\starttyping
+for e in xml.collected(xml.load('text.xml'),"title") do
+ -- e = the element that matched
+end
+\stoptyping
+
+The older variant is still supported but you can best use the previous variant.
+
+\starttyping
+for r, d, k in xml.elements(xml.load('text.xml'),"title") do
+ -- r = root of the title element
+ -- d = data table
+ -- k = index in data table
+end
+\stoptyping
+
+Here \type {d[k]} points to the \type {title} element and in this case all titles
+in the tree pass by. In practice this kind of code is encapsulated in function
+calls, like those returning elements one by one, or returning the first or last
+match. The result is then fed back into \TEX, possibly after being altered by an
+associated setup. We've seen the wrappers to such functions already in a previous
+chapter.
+
+In addition to the previously discussed expressions, one can add so called
+filters to the expression, for instance:
+
+\starttyping
+a/(b|c)/!d/e/text()
+\stoptyping
+
+In a filter, the last part of the \cmdinternal {cd:lpath} expression is a
+function call. The previous example returns the text of each element \type {e}
+that results from matching the expression. When running \TEX\ the following
+functions are available. Some are also available when using pure \LUA. In \TEX\
+you can often use one of the macros like \type {\xmlfirst} instead of a \type
+{\xmlfilter} with finalizer \type {first()}. The filter can be somewhat faster
+but that is hardly noticeable.
+
+\starttabulate[|l|l|p|]
+\NC \type {context()} \NC string \NC the serialized text with \TEX\ catcode regime \NC \NR
+%NC \type {ctxtext()} \NC string \NC \NC \NR
+\NC \type {function()} \NC string \NC depends on the function \NC \NR
+%
+\NC \type {name()} \NC string \NC the (remapped) namespace \NC \NR
+\NC \type {tag()} \NC string \NC the name of the element \NC \NR
+\NC \type {tags()} \NC list \NC the names of the element \NC \NR
+%
+\NC \type {text()} \NC string \NC the serialized text \NC \NR
+\NC \type {upper()} \NC string \NC the serialized text uppercased \NC \NR
+\NC \type {lower()} \NC string \NC the serialized text lowercased \NC \NR
+\NC \type {stripped()} \NC string \NC the serialized text stripped \NC \NR
+\NC \type {lettered()} \NC string \NC the serialized text only letters (cf. \UNICODE) \NC \NR
+%
+\NC \type {count()} \NC number \NC the number of matches \NC \NR
+\NC \type {index()} \NC number \NC the matched index in the current path \NC \NR
+\NC \type {match()} \NC number \NC the matched index in the preceding path \NC \NR
+%
+%NC \type {lowerall()} \NC string \NC \NC \NR
+%NC \type {upperall()} \NC string \NC \NC \NR
+%
+\NC \type {attribute(name)} \NC content \NC returns the attribute with the given name \NC \NR
+\NC \type {chainattribute(name)} \NC content \NC sidem, but backtracks till one is found \NC \NR
+\NC \type {command(name)} \NC content \NC expands the setup with the given name for each found element \NC \NR
+\NC \type {position(n)} \NC content \NC processes the \type {n}\high{th} instance of the found element \NC \NR
+\NC \type {all()} \NC content \NC processes all instances of the found element \NC \NR
+%NC \type {default} \NC content \NC all \NC \NR
+\NC \type {reverse()} \NC content \NC idem in reverse order \NC \NR
+\NC \type {first()} \NC content \NC processes the first instance of the found element \NC \NR
+\NC \type {last()} \NC content \NC processes the last instance of the found element \NC \NR
+\NC \type {concat(...)} \NC content \NC concatinates the match \NC \NC \NR
+\NC \type {concatrange(from,to,...)} \NC content \NC concatinates a range of matches \NC \NC \NR
+\stoptabulate
+
+The extra arguments of the concatinators are: \type {separator} (string), \type
+{lastseparator} (string) and \type {textonly} (a boolean).
+
+These filters are in fact \LUA\ functions which means that if needed more of them
+can be added. Indeed this happens in some of the \XML\ related \MKIV\ modules,
+for instance in the \MATHML\ processor.
+
+\stopsection
+
+\startsection[title={example}]
+
+The number of commands is rather large and if you want to avoid them this is
+often possible. Take for instance:
+
+\starttyping
+\xmlall{#1}{/a/b[position()>3]}
+\stoptyping
+
+Alternatively you can use:
+
+\starttyping
+\xmlfilter{#1}{/a/b[position()>3]/all()}
+\stoptyping
+
+and actually this is also faster as internally it avoids a function call. Of
+course in practice this is hardly measurable.
+
+In previous examples we've already seen quite some expressions, and it might be
+good to point out that the syntax is modelled after \XSLT\ but is not quite the
+same. The reason is that we started with a rather minimal system and have already
+styles in use that depend on compatibility.
+
+\starttyping
+namespace:// axis node(set) [expr 1]..[expr n] / ... / filter
+\stoptyping
+
+When we are inside a \CONTEXT\ run, the namespace is \type {tex}. Hoewever, if
+you want not to print back to \TEX\ you need to be more explicit. Say that we
+typeset examns and have a (not that logical) structure like:
+
+\starttyping
+<question>
+ <text>...</text>
+ <answer>
+ <item>one</item>
+ <item>two</item>
+ <item>three</item>
+ </answer>
+ <alternative>
+ <condition>true</condition>
+ <score>1</score>
+ </alternative>
+ <alternative>
+ <condition>false</condition>
+ <score>0</score>
+ </alternative>
+ <alternative>
+ <condition>true</condition>
+ <score>2</score>
+ </alternative>
+</question>
+\stoptyping
+
+Say that we typeset the questions with:
+
+\starttyping
+\startxmlsetups question
+ \blank
+ score: \xmlfunction{#1}{totalscore}
+ \blank
+ \xmlfirst{#1}{text}
+ \startitemize
+ \xmlfilter{#1}{/answer/item/command(answer:item)}
+ \stopitemize
+ \endgraf
+ \blank
+\stopxmlsetups
+\stoptyping
+
+Each item in the answer results in a call to:
+
+\starttyping
+\startxmlsetups answer:item
+ \startitem
+ \xmlflush{#1}
+ \endgraf
+ \xmlfilter{#1}{../../alternative[position()=rootposition()]/
+ condition/command(answer:condition)}
+ \stopitem
+\stopxmlsetups
+\stoptyping
+
+\starttyping
+\startxmlsetups answer:condition
+ \endgraf
+ condition: \xmlflush{#1}
+ \endgraf
+\stopxmlsetups
+\stoptyping
+
+Now, there are two rather special filters here. The first one involves
+calculating the total score. As we look forward we use a function to deal with
+this.
+
+\starttyping
+\startluacode
+function xml.functions.totalscore(root)
+ local score = 0
+ for e in xml.collected(root,"/alternative") do
+ score = score + xml.filter(e,"xml:///score/number()") or 0
+ end
+ tex.write(score)
+end
+\stopluacode
+\stoptyping
+
+Watch how we use the namespace to keep the results at the \LUA\ end.
+
+The second special trick shown here is to limit a match using the current
+position of the root (\type {#}) match.
+
+As you can see, a path expression can be more than just filtering a few nodes. At
+the end of this manual you will find a bunch of examples.
+
+\stopsection
+
+\startsection[title={tables}]
+
+If you want to know how the internal \XML\ tables look you can print such a
+table:
+
+\starttyping
+print(table.serialize(e))
+\stoptyping
+
+This produces for instance:
+
+% s = xml.convert("<document><demo label='whatever'>some text</demo></document>")
+% print(table.serialize(xml.filter(s,"demo")[1]))
+
+\starttyping
+t={
+ ["at"]={
+ ["label"]="whatever",
+ },
+ ["dt"]={ "some text" },
+ ["ns"]="",
+ ["rn"]="",
+ ["tg"]="demo",
+}
+\stoptyping
+
+The \type {rn} entry is the renamed namespace (when renaming is applied). If you
+see tags like \type {@pi@} this means that we don't have an element, but (in this
+case) a processing instruction.
+
+\starttabulate[|l|p|]
+\NC \type {@rt@} \NC the root element \NC \NR
+\NC \type {@dd@} \NC document definition \NC \NR
+\NC \type {@cm@} \NC comment, like \type {<!-- whatever -->} \NC \NR
+\NC \type {@cd@} \NC so called \type {CDATA} \NC \NR
+\NC \type {@pi@} \NC processing instruction, like \type {<?whatever we want ?>} \NC \NR
+\stoptabulate
+
+There are many ways to deal with the content, but in the perspective of \TEX\
+only a few matter.
+
+\starttabulate[|l|p|]
+\NC \type {xml.sprint(e)} \NC print the content to \TEX\ and apply setups if needed \NC \NR
+\NC \type {xml.tprint(e)} \NC print the content to \TEX\ (serialize elements verbose) \NC \NR
+\NC \type {xml.cprint(e)} \NC print the content to \TEX\ (used for special content) \NC \NR
+\stoptabulate
+
+Keep in mind that anything low level that you uncover is not part of the official
+interface unless mentioned in this manual.
+
+\stopsection
+
+\stopchapter
+
+\stopcomponent
diff --git a/doc/context/sources/general/manuals/xml/xml-mkiv-filtering.tex b/doc/context/sources/general/manuals/xml/xml-mkiv-filtering.tex
new file mode 100644
index 000000000..5bb5a35de
--- /dev/null
+++ b/doc/context/sources/general/manuals/xml/xml-mkiv-filtering.tex
@@ -0,0 +1,262 @@
+\environment xml-mkiv-style
+
+\startcomponent xml-mkiv-filtering
+
+\startchapter[title={Filtering content}]
+
+\startsection[title={\TEX\ versus \LUA}]
+
+It will not come as a surprise that we can access \XML\ files from \TEX\ as well
+as from \LUA. In fact there are two methods to deal with \XML\ in \LUA. First
+there are the low level \XML\ functions in the \type {xml} namespace. On top of
+those functions there is a set of functions in the \type {lxml} namespace that
+deals with \XML\ in a more \TEX ie way. Most of these have similar commands at
+the \TEX\ end.
+
+\startbuffer
+\startxmlsetups first:demo:one
+ \xmlfilter {#1} {artist/name[text()='Randy Newman']/..
+ /albums/album[position()=3]/command(first:demo:two)}
+\stopxmlsetups
+
+\startxmlsetups first:demo:two
+ \blank \start \tt
+ \xmldisplayverbatim{#1}
+ \stop \blank
+\stopxmlsetups
+
+\xmlprocessfile{demo}{music-collection.xml}{first:demo:one}
+\stopbuffer
+
+\typebuffer
+
+This gives the following snippet of verbatim \XML\ code. The indentation is
+conform the indentation in the whole \XML\ file. \footnote {The (probably
+outdated) \XML\ file contains the collection stores on my slimserver instance.
+You can use the \type {mtxrun --script flac} to generate such files.}
+
+\doifmodeelse {atpragma} {
+ \getbuffer
+} {
+ \typefile{xml-mkiv-01.xml}
+}
+
+An alternative written in \LUA\ looks as follows:
+
+\startbuffer
+\blank \start \tt \startluacode
+ local m = lxml.load("mine","music-collection.xml") -- m == lxml.id("mine")
+ local p = "artist/name[text()='Randy Newman']/../albums/album[position()=4]"
+ local l = lxml.filter(m,p) -- returns a list (with one entry)
+ lxml.displayverbatim(l[1])
+\stopluacode \stop \blank
+\stopbuffer
+
+\typebuffer
+
+This produces:
+
+\doifmodeelse {atpragma} {
+ \getbuffer
+} {
+ \typefile{xml-mkiv-02.xml}
+}
+
+You can use both methods mixed but in practice we will use the \TEX\ commands in
+regular styles and the mixture in modules, for instance in those dealing with
+\MATHML\ and cals tables. For complex matters you can write your own finalizers
+(the last action to be taken in a match) in \LUA\ and use them at the \TEX\ end.
+
+\stopsection
+
+\startsection[title={a few details}]
+
+In \CONTEXT\ setups are a rather common variant on macros (\TEX\ commands) but
+with their own namespace. An example of a setup is:
+
+\starttyping
+\startsetup doc:print
+ \setuppapersize[A4][A4]
+\stopsetup
+
+\startsetup doc:screen
+ \setuppapersize[S6][S4]
+\stopsetup
+\stoptyping
+
+Given the previous definitions, later on we can say something like:
+
+\starttyping
+\doifmodeelse {paper} {
+ \setup[doc:print]
+} {
+ \setup[doc:screen]
+}
+\stoptyping
+
+Another example is:
+
+\starttyping
+\startsetup[doc:header]
+ \marking[chapter]
+ \space
+ --
+ \space
+ \pagenumber
+\stopsetup
+\stoptyping
+
+in combination with:
+
+\starttyping
+\setupheadertexts[\setup{doc:header}]
+\stoptyping
+
+Here the advantage is that instead of ending up with an unreadable header
+definitions, we use a nicely formatted setup. An important property of setups and
+the reason why they were introduced long ago is that spaces and newlines are
+ignored in the definition. This means that we don't have to worry about so called
+spurious spaces but it also means that when we do want a space, we have to use
+the \type {\space} command.
+
+The only difference between setups and \XML\ setups is that the following ones
+get an argument (\type {#1}) that reflects the current node in the \XML\ tree.
+
+\stopsection
+
+\startsection[title={CDATA}]
+
+What to do with \type {CDATA}? There are a few methods at tle \LUA\ end for
+dealing with it but here we just mention how you can influence the rendering.
+There are four macros that play a role here:
+
+\starttyping
+\unexpanded\def\xmlcdataobeyedline {\obeyedline}
+\unexpanded\def\xmlcdataobeyedspace{\strut\obeyedspace}
+\unexpanded\def\xmlcdatabefore {\begingroup\tt}
+\unexpanded\def\xmlcdataafter {\endgroup}
+\stoptyping
+
+Technically you can overload them but beware of side effects. Normally you won't
+see much \type {CDATA} and whenever we do, it involves special data that needs
+very special treatment anyway.
+
+\stopsection
+
+\startsection[title={Entities}]
+
+As usual with any way of encoding documents you need escapes in order to encode
+the characters that are used in tagging the content, embedding comments, escaping
+special characters in strings (in programming languages), etc. In \XML\ this
+means that in order characters like \type {<} you need an escape like \type
+{&lt;} and in order then to encode an \type {&} you need \type {&amp;}.
+
+In a typesetting workflow using a programming language like \TEX, another problem
+shows up. There we have different special characters, like \type {$ $} for triggering
+math, but also the backslash, braces etc. Even one such special character is already
+enough to have yet another escaping mechanism at work.
+
+Ideally a user should not worry about these issues but it helps figuring out issues
+when you know what happens under the hood. Also it is good to know that in the
+code there are several ways to deal with these issues. Take the following document:
+
+\starttyping
+<text>
+ Here we have a bit of a &lt;&mess&gt;:
+
+ # &#35;
+ % &#37;
+ \ &#92;
+ { &#123;
+ | &#124;
+ } &#125;
+ ~ &#126;
+</text>
+\stoptyping
+
+When the file is read the \type {&lt;} entity will be replaced by \type {<} and
+the \type {&gt;} by \type {>}. The numeric entities will be replaced by the
+characters they refer to. The \type {&mess} is kind of special. We do preload
+a huge list of more or less standardized entities but \type {mess} is not in
+there. However, it is possible to have it defined in the document preamble, like:
+
+\starttyping
+<!DOCTYPE dummy SYSTEM "dummy.dtd" [
+ <!ENTITY mess "what a mess" >
+]>
+\stoptyping
+
+or even this:
+
+\starttyping
+<!DOCTYPE dummy SYSTEM "dummy.dtd" [
+ <!ENTITY mess "<p>what a mess</p>" >
+]>
+\stoptyping
+
+You can also define it in your document style using one of:
+
+\startxmlcmd {\cmdbasicsetup{xmlsetentity}}
+ replaces entity with name \cmdinternal {cd:name} by \cmdinternal {cd:text}
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmltexentity}}
+ replaces entity with name \cmdinternal {cd:name} by \cmdinternal {cd:text}
+ typeset under a \TEX\ regime
+\stopxmlcmd
+
+Such a definition will always have a higher priority than the one defined
+in the document. Anyway, when the document is read in all entities are
+resolved and those that need a special treatment because they map to some
+text are stored in such a way that we can roundtrip them. As a consequence,
+as soon as the content gets pushed into \TEX, we need not only to intercept
+special characters but also have to make sure that the following works:
+
+\starttyping
+\xmltexentity {tex} {\TEX}
+\stoptyping
+
+Here the backslash starts a control sequence while in regular content a
+backslash is just that: a backslash.
+
+Special characters are really special when we have to move text around
+in a \TEX\ ecosystem.
+
+\starttyping
+<text>
+ <title>About #3</title>
+</text>
+\stoptyping
+
+If we map and define title as follows:
+
+\starttyping
+\startxmlsetup xml:title
+ \title{\xmlflush{#1}}
+\stopxmlsetup
+\stoptyping
+
+normally something \type {\xmlflush {id::123}} will be written to the
+auxiliary file and in most cases that is quite okay, but if we have this:
+
+\starttyping
+\setuphead[title][expansion=yes]
+\stoptyping
+
+then we don't want the \type {#} to end up as hash because later on \TEX\
+can get very confused about it because it sees some argument then in a
+probably unexpected way. This is solved by escaping the hash like this:
+
+\starttyping
+About \Ux{23}3
+\stoptyping
+
+The \type {\Ux} command will convert its hexadecimal argument into a
+character. Of course one then needs to typeset such a text under a \TEX\
+character regime but that is normally the case anyway.
+
+\stopsection
+
+\stopchapter
+
+\stopcomponent
diff --git a/doc/context/sources/general/manuals/xml/xml-mkiv-introduction.tex b/doc/context/sources/general/manuals/xml/xml-mkiv-introduction.tex
new file mode 100644
index 000000000..e7f0124da
--- /dev/null
+++ b/doc/context/sources/general/manuals/xml/xml-mkiv-introduction.tex
@@ -0,0 +1,42 @@
+\environment xml-mkiv-style
+
+\startcomponent xml-mkiv-introduction
+
+\startchapter[title={Introduction}]
+
+This manual presents the \MKIV\ way of dealing with \XML. Although the
+traditional \MKII\ streaming parser has a charming simplicity in its control, for
+complex documents the tree based \MKIV\ method is more convenient. It is for this
+reason that the old method has been removed from \MKIV. If you are familiar with
+\XML\ processing in \MKII, then you will have noticed that the \MKII\ commands
+have \type {XML} in their name. The \MKIV\ commands have a lowercase \type {xml}
+in their names. That way there is no danger for confusion or a mixup.
+
+You may wonder why we do these manipulations in \TEX\ and not use \XSLT\ (or
+other transformation methods) instead. The advantage of an integrated approach is
+that it simplifies usage. Think of not only processing the document, but also
+using \XML\ for managing resources in the same run. An \XSLT\ approach is just as
+verbose (after all, you still need to produce \TEX\ code) and probably less
+readable. In the case of \MKIV\ the integrated approach is also faster and gives
+us the option to manipulate content at runtime using \LUA. It has the additional
+advantage that to some extend we can handle a mix of \TEX\ and \XML\ because we
+know when we're doing one or the other.
+
+This manual is dedicated to Taco Hoekwater, one of the first \CONTEXT\ users, and
+also the first to use it for processing \XML. Who could have thought at that time
+that we would have a more convenient way of dealing with those angle brackets.
+The second version for this manual is dedicated to Thomas Schmitz, a power user
+who occasionally became victim of the evolving mechanisms.
+
+\blank
+
+\startlines
+Hans Hagen
+\PRAGMA
+Hasselt NL
+2008\endash2016
+\stoplines
+
+\stopchapter
+
+\stopcomponent
diff --git a/doc/context/sources/general/manuals/xml/xml-mkiv-lookups.tex b/doc/context/sources/general/manuals/xml/xml-mkiv-lookups.tex
new file mode 100644
index 000000000..e6afaa948
--- /dev/null
+++ b/doc/context/sources/general/manuals/xml/xml-mkiv-lookups.tex
@@ -0,0 +1,314 @@
+\environment xml-mkiv-style
+
+\startcomponent xml-mkiv-lookups
+
+\startchapter[title={Lookups using lpaths}]
+
+\startsection[title={introduction}]
+
+There is not that much system in the following examples. They resulted from tests
+with different documents. The current implementation evolved out of the
+experimental code. For instance, I decided to add the multiple expressions in row
+handling after a few email exchanges with Jean|-|Michel Huffen.
+
+One of the main differences between the way \XSLT\ resolves a path and our way is
+the anchor. Take:
+
+\starttyping
+/something
+something
+\stoptyping
+
+The first one anchors in the current (!) element so it will only consider direct
+children. The second one does a deep lookup and looks at the descendants as well.
+Furthermore we have a few extra shortcuts like \type {**} in \type {a/**/b} which
+represents all descendants.
+
+The expressions (between square brackets) has to be valid \LUA\ and some
+preprocessing is done to resolve the built in functions. So, you might use code
+like:
+
+\starttyping
+my_lpeg_expression:match(text()) == "whatever"
+\stoptyping
+
+given that \type {my_lpeg_expression} is known. In the examples below we use the
+visualizer to show the steps. Some are shown more than once as part of a set.
+
+\stopsection
+
+\startsection[title={special cases}]
+
+\xmllshow{}
+\xmllshow{*}
+\xmllshow{.}
+\xmllshow{/}
+
+\stopsection
+
+\startsection[title={wildcards}]
+
+\xmllshow{*}
+\xmllshow{*:*}
+\xmllshow{/*}
+\xmllshow{/*:*}
+\xmllshow{*/*}
+\xmllshow{*:*/*:*}
+
+\xmllshow{a/*}
+\xmllshow{a/*:*}
+\xmllshow{/a/*}
+\xmllshow{/a/*:*}
+
+\xmllshow{/*}
+\xmllshow{/**}
+\xmllshow{/***}
+
+\stopsection
+
+\startsection[title={multiple steps}]
+
+\xmllshow{answer}
+\xmllshow{answer/test/*}
+\xmllshow{answer/test/child::}
+\xmllshow{answer/*}
+\xmllshow{answer/*[tag()='p' and position()=1 and text()!='']}
+
+\stopsection
+
+\startsection[title={pitfals}]
+
+\xmllshow{[oneof(lower(@encoding),'tex','context','ctx')]}
+\xmllshow{.[oneof(lower(@encoding),'tex','context','ctx')]}
+
+\stopsection
+
+\startsection[title={more special cases}]
+
+\xmllshow{**}
+\xmllshow{*}
+\xmllshow{..}
+\xmllshow{.}
+\xmllshow{//}
+\xmllshow{/}
+
+\xmllshow{**/}
+\xmllshow{**/*}
+\xmllshow{**/.}
+\xmllshow{**//}
+
+\xmllshow{*/}
+\xmllshow{*/*}
+\xmllshow{*/.}
+\xmllshow{*//}
+
+\xmllshow{/**/}
+\xmllshow{/**/*}
+\xmllshow{/**/.}
+\xmllshow{/**//}
+
+\xmllshow{/*/}
+\xmllshow{/*/*}
+\xmllshow{/*/.}
+\xmllshow{/*//}
+
+\xmllshow{./}
+\xmllshow{./*}
+\xmllshow{./.}
+\xmllshow{.//}
+
+\xmllshow{../}
+\xmllshow{../*}
+\xmllshow{../.}
+\xmllshow{..//}
+
+\stopsection
+
+\startsection[title={more wildcards}]
+
+\xmllshow{one//two}
+\xmllshow{one/*/two}
+\xmllshow{one/**/two}
+\xmllshow{one/***/two}
+\xmllshow{one/x//two}
+\xmllshow{one//x/two}
+\xmllshow{//x/two}
+
+\stopsection
+
+\startsection[title={special axis}]
+
+\xmllshow{descendant::whocares/ancestor::whoknows}
+\xmllshow{descendant::whocares/ancestor::whoknows/parent::}
+\xmllshow{descendant::whocares/ancestor::}
+\xmllshow{child::something/child::whatever/child::whocares}
+\xmllshow{child::something/child::whatever/child::whocares|whoknows}
+\xmllshow{child::something/child::whatever/child::(whocares|whoknows)}
+\xmllshow{child::something/child::whatever/child::!(whocares|whoknows)}
+\xmllshow{child::something/child::whatever/child::(whocares)}
+\xmllshow{child::something/child::whatever/child::(whocares)[position()>2]}
+\xmllshow{child::something/child::whatever[position()>2][position()=1]}
+\xmllshow{child::something/child::whatever[whocares][whocaresnot]}
+\xmllshow{child::something/child::whatever[whocares][not(whocaresnot)]}
+\xmllshow{child::something/child::whatever/self::whatever}
+
+There is also \type {last-match::} that starts with the last found set of nodes.
+This can save some run time when you do lots of tests combined with a same check
+afterwards. There is however one pitfall: you never know what is done with that
+last match in the setup that gets called nested. Take the following example:
+
+\starttyping
+\startbuffer[test]
+<something>
+ <crap> <crapa> <crapb> <crapc> <crapd>
+ <crape>
+ done 1
+ </crape>
+ </crapd> </crapc> </crapb> </crapa>
+ <crap> <crapa> <crapb> <crapc> <crapd>
+ <crape>
+ done 2
+ </crape>
+ </crapd> </crapc> </crapb> </crapa>
+ <crap> <crapa> <crapb> <crapc> <crapd>
+ <crape>
+ done 3
+ </crape>
+ </crapd> </crapc> </crapb> </crapa>
+</something>
+\stopbuffer
+\stoptyping
+
+One way to filter the content is this:
+
+\starttyping
+\xmldoif {#1} {/crap/crapa/crapb/crapc/crapd/crape} {
+ some action
+}
+\stoptyping
+
+It is not unlikely that you will do something like this:
+
+\starttyping
+\xmlfirst {#1} {/crap/crapa/crapb/crapc/crapd/crape} {
+ \xmlfirst{#1}{/crap/crapa/crapb/crapc/crapd/crape}
+}
+\stoptyping
+
+This means that the path is resolved twice but that can be avoided as
+follows:
+
+\starttyping
+\xmldoif{#1}{/crap/crapa/crapb/crapc/crapd/crape}{
+ \xmlfirst{#1}{last-match::}
+}
+\stoptyping
+
+But the next is now guaranteed to work:
+
+\starttyping
+\xmldoif{#1}{/crap/crapa/crapb/crapc/crapd/crape}{
+ \xmlfirst{#1}{last-match::}
+ \xmllast{#1}{last-match::}
+}
+\stoptyping
+
+Because the first one can have done some lookup the last match can be replaced
+and the second call will give unexpected results. You can overcome this with:
+
+\starttyping
+\xmldoif{#1}{/crap/crapa/crapb/crapc/crapd/crape}{
+ \xmlpushmatch
+ \xmlfirst{#1}{last-match::}
+ \xmlpopmatch
+}
+\stoptyping
+
+Does it pay off? Here are some timings of a 10.000 times text and lookup
+like the previous (on a decent January 2016 laptop):
+
+\starttabulate[|r|l|]
+\NC 0.239 \NC \type {\xmldoif {...} {...}} \NC \NR
+\NC 0.292 \NC \type {\xmlfirst {...} {...}} \NC \NR
+\NC 0.538 \NC \type {\xmldoif {...} {...} + \xmlfirst {...} {...}} \NC \NR
+\NC 0.338 \NC \type {\xmldoif {...} {...} + \xmlfirst {...} {last-match::}} \NC \NR
+\NC 0.349 \NC \type {+ \xmldoif {...} {...} + \xmlfirst {...} {last-match::}-} \NC \NR
+\stoptabulate
+
+So, pushing and popping (the last row) is a bit slower than not doing that but it
+is still much faster than not using \type {last-match::} at all. As a shortcut
+you can use \type {=}, as in:
+
+\starttyping
+\xmlfirst{#1}{=}
+\stoptyping
+
+You can even do this:
+
+\starttyping
+\xmlall{#1}{last-match::/text()}
+\stoptyping
+
+or
+
+\starttyping
+\xmlall{#1}{=/text()}
+\stoptyping
+
+
+\stopsection
+
+\startsection[title={some more examples}]
+
+\xmllshow{/something/whatever}
+\xmllshow{something/whatever}
+\xmllshow{/**/whocares}
+\xmllshow{whoknows/whocares}
+\xmllshow{whoknows}
+\xmllshow{whocares[contains(text(),'f') or contains(text(),'g')]}
+\xmllshow{whocares/first()}
+\xmllshow{whocares/last()}
+\xmllshow{whatever/all()}
+\xmllshow{whocares/position(2)}
+\xmllshow{whocares/position(-2)}
+\xmllshow{whocares[1]}
+\xmllshow{whocares[-1]}
+\xmllshow{whocares[2]}
+\xmllshow{whocares[-2]}
+\xmllshow{whatever[3]/attribute(id)}
+\xmllshow{whatever[2]/attribute('id')}
+\xmllshow{whatever[3]/text()}
+\xmllshow{/whocares/first()}
+\xmllshow{/whocares/last()}
+
+\xmllshow{xml://whatever/all()}
+\xmllshow{whatever/all()}
+\xmllshow{//whocares}
+\xmllshow{..[2]}
+\xmllshow{../*[2]}
+
+\xmllshow{/(whocares|whocaresnot)}
+\xmllshow{/!(whocares|whocaresnot)}
+\xmllshow{/!whocares}
+
+\xmllshow{/interface/command/command(xml:setups:register)}
+\xmllshow{/interface/command[@name='xxx']/command(xml:setups:typeset)}
+\xmllshow{/arguments/*}
+\xmllshow{/sequence/first()}
+\xmllshow{/arguments/text()}
+\xmllshow{/sequence/variable/first()}
+\xmllshow{/interface/define[@name='xxx']/first()}
+\xmllshow{/parameter/command(xml:setups:parameter:measure)}
+
+\xmllshow{/(*:library|figurelibrary)/*:figure/*:label}
+\xmllshow{/(*:library|figurelibrary)/figure/*:label}
+\xmllshow{/(*:library|figurelibrary)/figure/label}
+\xmllshow{/(*:library|figurelibrary)/figure:*/label}
+
+\xmlshow {whatever//br[tag(1)='br']}
+
+\stopsection
+
+\stopchapter
+
+\stopcomponent
diff --git a/doc/context/sources/general/manuals/xml/xml-mkiv-lpath.tex b/doc/context/sources/general/manuals/xml/xml-mkiv-lpath.tex
new file mode 100644
index 000000000..9c8b853c8
--- /dev/null
+++ b/doc/context/sources/general/manuals/xml/xml-mkiv-lpath.tex
@@ -0,0 +1,207 @@
+\input lxml-ctx.mkiv
+
+\ctxlua{dofile("t:/sources/lxml-lpt.lua")}
+
+\startbuffer[xmltest]
+<?xml version='1.0'?>
+
+<!-- this is a test file -->
+
+<something id='1'>
+ <x:whatever id='1.1'>
+ <whocares id='1.1.1'>
+ test a
+ </whocares>
+ <whocaresnot id='1.1.2'>
+ test b
+ </whocaresnot>
+ </x:whatever>
+ <whatever id='2'>
+ <whocares id='2.1'>
+ test c
+ </whocares>
+ <whocaresnot id='2.2'>
+ test d
+ </whocaresnot>
+ </whatever>
+ <whatever id='3'>
+ test e
+ </whatever>
+ <whatever id='4' test="xxx">
+ <whocares id='4.1'>
+ test f
+ </whocares>
+ <whocares id='4.2'>
+ test g
+ </whocares>
+ </whatever>
+ <whatever id='5' test="xxx">
+ <whoknows id='5.1'>
+ <whocares id='5.1.1'>
+ test h
+ </whocares>
+ </whoknows>
+ <whoknows id='5.2'>
+ <whocaresnot id='5.2.1'>
+ test i
+ </whocaresnot>
+ </whoknows>
+ <whoknows id='5.3'>
+ <whocares id='5.3.1'>
+ test j
+ </whocares>
+ </whoknows>
+ </whatever>
+</something>
+\stopbuffer
+
+% \enabletrackers[xml.lparse]
+
+\setuplayout[width=middle,height=middle,header=1cm,footer=1cm,topspace=2cm,backspace=2cm]
+\setupbodyfont[10pt]
+
+\setfalse\xmllshowbuffer
+
+\starttext
+
+\xmllshow{/(*:library|figurelibrary)/*:figure/*:label}
+\xmllshow{/(*:library|figurelibrary)/figure/*:label}
+\xmllshow{/(*:library|figurelibrary)/figure/label}
+\xmllshow{/(*:library|figurelibrary)/figure:*/label}
+
+% \xmllshow{collection[@version='all']/resources/manual[match()==1]/paper/command(xml:overview)}
+% \xmllshow{collection/resources/manual[match()=1]/paper/command(xml:overview)}
+
+% \xmllshow{answer//oeps}
+% \xmllshow{answer/*/oeps}
+% \xmllshow{answer/**/oeps}
+% \xmllshow{answer/***/oeps}
+% \xmllshow{answer/x//oeps}
+% \xmllshow{answer//x/oeps}
+% \xmllshow{//x/oeps}
+% \xmllshow{answer/test/*}
+% \xmllshow{answer/test/child::}
+% \xmllshow{answer/*}
+% \xmllshow{ oeps / answer / .. / * [tag()='p' and position()=1 and text()!=''] / oeps()}
+
+% \xmllshow{ artist / name [text()='Randy Newman'] / .. / albums / album [position()=3] / command(first:demo:two)}
+% \xmllshow{/exa:selectors/exa:selector/exa:list/component[count()>1]}
+
+\stoptext
+
+\xmllshow{/*}
+\xmllshow{child::}
+\xmllshow{child::test}
+\xmllshow{/test/test}
+\xmllshow{../theory/sections/section/exercises}
+\xmllshow{../training/practicalassignments}
+\xmllshow{../../Outcome[position()=rootposition()]/Condition/command(xml:answer:mc:condition)}
+
+% \stoptext
+
+% \typebuffer[xmltest] \page
+
+\xmllshowbuffer{xmltest}{**}{id}
+\xmllshowbuffer{xmltest}{*}{id}
+\xmllshowbuffer{xmltest}{..}{id}
+\xmllshowbuffer{xmltest}{.}{id}
+\xmllshowbuffer{xmltest}{//}{id}
+\xmllshowbuffer{xmltest}{/}{id}
+
+\xmllshowbuffer{xmltest}{**/}{id}
+\xmllshowbuffer{xmltest}{**/*}{id}
+\xmllshowbuffer{xmltest}{**/.}{id}
+\xmllshowbuffer{xmltest}{**//}{id}
+
+\xmllshowbuffer{xmltest}{*/}{id}
+\xmllshowbuffer{xmltest}{*/*}{id}
+\xmllshowbuffer{xmltest}{*/.}{id}
+\xmllshowbuffer{xmltest}{*//}{id}
+
+\xmllshowbuffer{xmltest}{/**/}{id}
+\xmllshowbuffer{xmltest}{/**/*}{id}
+\xmllshowbuffer{xmltest}{/**/.}{id}
+\xmllshowbuffer{xmltest}{/**//}{id}
+
+\xmllshowbuffer{xmltest}{/*/}{id}
+\xmllshowbuffer{xmltest}{/*/*}{id}
+\xmllshowbuffer{xmltest}{/*/.}{id}
+\xmllshowbuffer{xmltest}{/*//}{id}
+
+\xmllshowbuffer{xmltest}{./}{id}
+\xmllshowbuffer{xmltest}{./*}{id}
+\xmllshowbuffer{xmltest}{./.}{id}
+\xmllshowbuffer{xmltest}{.//}{id}
+
+\xmllshowbuffer{xmltest}{../}{id}
+\xmllshowbuffer{xmltest}{../*}{id}
+\xmllshowbuffer{xmltest}{../.}{id}
+\xmllshowbuffer{xmltest}{..//}{id}
+
+\xmllshowbuffer{xmltest}{descendant::whocares/ancestor::whoknows}{id}
+\xmllshowbuffer{xmltest}{descendant::whocares/ancestor::whoknows/parent::}{id}
+\xmllshowbuffer{xmltest}{descendant::whocares/ancestor::}{id}
+\xmllshowbuffer{xmltest}{child::something/child::whatever/child::whocares}{id}
+\xmllshowbuffer{xmltest}{child::something/child::whatever/child::whocares|whoknows}{id}
+\xmllshowbuffer{xmltest}{child::something/child::whatever/child::(whocares|whoknows)}{id}
+\xmllshowbuffer{xmltest}{child::something/child::whatever/child::!(whocares|whoknows)}{id}
+\xmllshowbuffer{xmltest}{child::something/child::whatever/child::(whocares)}{id}
+\xmllshowbuffer{xmltest}{child::something/child::whatever/child::(whocares)[position()>2]}{id}
+\xmllshowbuffer{xmltest}{child::something/child::whatever[position()>2][position()=1]}{id}
+\xmllshowbuffer{xmltest}{child::something/child::whatever[whocares][whocaresnot]}{id}
+\xmllshowbuffer{xmltest}{child::something/child::whatever[whocares][not(whocaresnot)]}{id}
+\xmllshowbuffer{xmltest}{child::something/child::whatever/self::whatever}{id}
+\xmllshowbuffer{xmltest}{/something/whatever}{id}
+\xmllshowbuffer{xmltest}{something/whatever}{id}
+\xmllshowbuffer{xmltest}{/**/whocares}{id}
+\xmllshowbuffer{xmltest}{whoknows/whocares}{id}
+\xmllshowbuffer{xmltest}{whoknows}{id}
+\xmllshowbuffer{xmltest}{whocares[contains(text(),'f') or contains(text(),'g')]}{id}
+\xmllshowbuffer{xmltest}{whocares/first()}{id}
+\xmllshowbuffer{xmltest}{whocares/last()}{id}
+\xmllshowbuffer{xmltest}{whatever/all()}{id}
+\xmllshowbuffer{xmltest}{whocares/position(2)}{id}
+\xmllshowbuffer{xmltest}{whocares/position(-2)}{id}
+\xmllshowbuffer{xmltest}{whocares[1]}{id}
+\xmllshowbuffer{xmltest}{whocares[-1]}{id}
+\xmllshowbuffer{xmltest}{whocares[2]}{id}
+\xmllshowbuffer{xmltest}{whocares[-2]}{id}
+\xmllshowbuffer{xmltest}{whatever[3]/attribute(id)}{id}
+\xmllshowbuffer{xmltest}{whatever[2]/attribute('id')}{id}
+\xmllshowbuffer{xmltest}{whatever[3]/text()}{id}
+\xmllshowbuffer{xmltest}{/whocares/first()}{id}
+\xmllshowbuffer{xmltest}{/whocares/last()}{id}
+
+\xmllshowbuffer{xmltest}{xml://whatever/all()}{id}
+\xmllshowbuffer{xmltest}{whatever/all()}{id}
+\xmllshowbuffer{xmltest}{//whocares}{id}
+\xmllshowbuffer{xmltest}{..[2]}{id}
+\xmllshowbuffer{xmltest}{../*[2]}{id}
+
+\xmllshowbuffer{xmltest}{/(whocares|whocaresnot)}{id}
+\xmllshowbuffer{xmltest}{/!(whocares|whocaresnot)}{id}
+\xmllshowbuffer{xmltest}{/!whocares}{id}
+
+% \page
+
+% \xmllshow{/interface/command/command(xml:setups:register)}
+% \xmllshow{/interface/command[@name='xxx']/command(xml:setups:typeset)}
+% \xmllshow{/arguments/*}
+% \xmllshow{/sequence/first()}
+% \xmllshow{/arguments/text()}
+% \xmllshow{/sequence/variable/first()}
+% \xmllshow{/interface/define[@name='xxx']/first()}
+% \xmllshow{/parameter/command(xml:setups:parameter:measure)}
+
+% \page
+
+% \xmllshow{interface/command/command(xml:setups:register)}
+% \xmllshow{interface/command[@name='xxx']/command(xml:setups:typeset)}
+% \xmllshow{arguments/*}
+% \xmllshow{sequence/first()}
+% \xmllshow{arguments/text()}
+% \xmllshow{sequence/variable/first()}
+% \xmllshow{interface/define[@name='xxx']/first()}
+% \xmllshow{parameter/command(xml:setups:parameter:measure)}
+
+\stoptext
diff --git a/doc/context/sources/general/manuals/xml/xml-mkiv-style.tex b/doc/context/sources/general/manuals/xml/xml-mkiv-style.tex
new file mode 100644
index 000000000..8bcd74086
--- /dev/null
+++ b/doc/context/sources/general/manuals/xml/xml-mkiv-style.tex
@@ -0,0 +1,155 @@
+\startenvironment xml-mkiv-style
+
+\input lxml-ctx.mkiv
+
+\settrue \xmllshowtitle
+\setfalse\xmllshowwarning
+
+\usemodule[set-11]
+
+\loadsetups[i-context]
+
+% \definehspace[squad][1em plus .25em minus .25em]
+
+\usemodule[abr-02]
+
+\setuplayout
+ [location=middle,
+ marking=on,
+ backspace=20mm,
+ cutspace=20mm,
+ topspace=15mm,
+ header=15mm,
+ footer=15mm,
+ height=middle,
+ width=middle]
+
+\setuppagenumbering
+ [alternative=doublesided,
+ location=]
+
+\setupfootertexts
+ [][pagenumber]
+
+\setupheadertexts
+ [][chapter]
+
+\setupheader
+ [color=colortwo,
+ style=bold]
+
+\setupfooter
+ [color=colortwo,
+ style=bold]
+
+\setuphead
+ [chapter]
+ [page={yes,header,right},
+ header=empty,
+ style=\bfc]
+
+\setupsectionblock
+ [page={yes,header,right}]
+
+\starttexdefinition unexpanded section:chapter:number #1
+ \doifmode{*sectionnumber} {
+ \bf
+ \llap{<\enspace}#1\enspace>
+ }
+\stoptexdefinition
+
+\starttexdefinition unexpanded section:section:number #1
+ \doifmode{*sectionnumber} {
+ \bf
+ \llap{<<\enspace}#1\enspace>>
+ }
+\stoptexdefinition
+
+\starttexdefinition unexpanded section:subsection:number #1
+ \doifmode{*sectionnumber} {
+ \bf
+ \llap{<<<\enspace}#1\enspace>>>
+ }
+\stoptexdefinition
+
+\setuphead[chapter] [numbercolor=black,numbercommand=\texdefinition{section:chapter:number}]
+\setuphead[section] [numbercolor=black,numbercommand=\texdefinition{section:section:number}]
+\setuphead[subsection] [numbercolor=black,numbercommand=\texdefinition{section:subsection:number}]
+\setuphead[subsubsection][numbercolor=,numbercommand=,before=\blank,after=\blank]
+
+\setuphead
+ [section]
+ [style=\bfa]
+
+\setuplist
+ [chapter]
+ [style=bold]
+
+\setupinteractionscreen
+ [option=doublesided]
+
+\setupalign
+ [tolerant,stretch]
+
+\setupwhitespace
+ [big]
+
+\setuptolerance
+ [tolerant]
+
+\doifelsemode {atpragma} {
+ \setupbodyfont[lucidaot,10pt]
+} {
+ \setupbodyfont[dejavu,10pt]
+}
+
+\definecolor[colorone] [b=.5]
+\definecolor[colortwo] [s=.3]
+\definecolor[colorthree][y=.5]
+
+\setuptype
+ [color=colorone]
+
+\setuptyping
+ [color=colorone]
+
+\setuphead
+ [lshowtitle]
+ [style=\tt,
+ color=colorone]
+
+\setuphead
+ [chapter,section]
+ [numbercolor=colortwo,
+ color=colorone]
+
+\definedescription
+ [xmlcmd]
+ [alternative=hanging,
+ width=line,
+ distance=1em,
+ margin=2em,
+ headstyle=monobold,
+ headcolor=colorone]
+
+\setupframedtext
+ [setuptext]
+ [framecolor=colorone,
+ rulethickness=1pt,
+ corner=round]
+
+\usemodule[punk]
+
+\usetypescript[punk]
+
+\definelayer
+ [page]
+ [width=\paperwidth,
+ height=\paperheight]
+
+\definestartstop
+ [smallexample]
+ [before={\blank\bgroup\ss\small\setupwhitespace[medium]\setupblank[medium]},
+ after={\par\egroup\blank}]
+
+\stopenvironment
diff --git a/doc/context/sources/general/manuals/xml/xml-mkiv-titlepage.tex b/doc/context/sources/general/manuals/xml/xml-mkiv-titlepage.tex
new file mode 100644
index 000000000..427557214
--- /dev/null
+++ b/doc/context/sources/general/manuals/xml/xml-mkiv-titlepage.tex
@@ -0,0 +1,47 @@
+\environment xml-mkiv-style
+
+\startcomponent xml-mkiv-titlepage
+
+\setuplayout[page]
+
+\startstandardmakeup
+ \startfontclass[none] % nil the current fontclass since it may append its features
+ \EnableRandomPunk
+ \setlayerframed
+ [page]
+ [width=\paperwidth,height=\paperheight,
+ background=color,backgroundcolor=colorone,backgroundoffset=1ex,frame=off]
+ {}
+ \definedfont[demo@punk at 18pt]
+ \setbox\scratchbox\vbox {
+ \hsize\dimexpr\paperwidth+2ex\relax
+ \setupinterlinespace
+ \baselineskip 1\baselineskip plus 1pt minus 1pt
+ \raggedcenter
+ \color[colortwo]{\dorecurse{1000}{XML }}
+ }
+ \setlayer
+ [page]
+ [preset=middle]
+ {\vsplit\scratchbox to \dimexpr\paperheight+2ex\relax}
+ \definedfont[demo@punk at 90pt]
+ \setstrut
+ \setlayerframed
+ [page]
+ [preset=rightbottom,offset=10mm]
+ [foregroundcolor=colorthree,align=flushright,offset=overlay,frame=off]
+ {Dealing\\with XML in\\Con\TeX t MkIV}
+ \definedfont[demo@punk at 18pt]
+ \setstrut
+ \setlayerframed
+ [page]
+ [preset=righttop,offset=10mm,x=3mm,rotation=90]
+ [foregroundcolor=colorthree,align=flushright,offset=overlay,frame=off]
+ {Hans Hagen, Pragma ADE, \currentdate}
+ \tightlayer[page]
+ \stopfontclass
+\stopstandardmakeup
+
+\setuplayout
+
+\stopcomponent
diff --git a/doc/context/sources/general/manuals/xml/xml-mkiv-tricks.tex b/doc/context/sources/general/manuals/xml/xml-mkiv-tricks.tex
new file mode 100644
index 000000000..f8c65ecc9
--- /dev/null
+++ b/doc/context/sources/general/manuals/xml/xml-mkiv-tricks.tex
@@ -0,0 +1,814 @@
+\environment xml-mkiv-style
+
+\startcomponent xml-mkiv-tricks
+
+\startchapter[title={Tips and tricks}]
+
+\startsection[title={tracing}]
+
+It can be hard to debug code as much happens kind of behind the screens.
+Therefore we have a couple of tracing options. Of course you can typeset some
+status information, using for instance:
+
+\startxmlcmd {\cmdbasicsetup{xmlshow}}
+ typeset the tree given by \cmdinternal {cd:node}
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlinfo}}
+ typeset the name in the element given by \cmdinternal {cd:node}
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlpath}}
+ returns the complete path (including namespace prefix and index) of the
+ given \cmdinternal {cd:node}
+\stopxmlcmd
+
+\startbuffer[demo]
+<?xml version "1.0"?>
+<document>
+ <section>
+ <content>
+ <p>first</p>
+ <p><b>second</b></p>
+ </content>
+ </section>
+ <section>
+ <content>
+ <p><b>third</b></p>
+ <p>fourth</p>
+ </content>
+ </section>
+</document>
+\stopbuffer
+
+Say that we have the following \XML:
+
+\typebuffer[demo]
+
+and the next definitions:
+
+\startbuffer
+\startxmlsetups xml:demo:base
+ \xmlsetsetup{#1}{p|b}{xml:demo:*}
+\stopxmlsetups
+
+\startxmlsetups xml:demo:p
+ \xmlflush{#1}
+ \par
+\stopxmlsetups
+
+\startxmlsetups xml:demo:b
+ \par
+ \xmlpath{#1} : \xmlflush{#1}
+ \par
+\stopxmlsetups
+
+\xmlregisterdocumentsetup{example-10}{xml:demo:base}
+
+\xmlprocessbuffer{example-10}{demo}{}
+\stopbuffer
+
+\typebuffer
+
+This will give us:
+
+\blank \startpacked \getbuffer \stoppacked \blank
+
+If you use \type {\xmlshow} you will get a complete subtree which can
+be handy for tracing but can also lead to large documents.
+
+We also have a bunch of trackers that can be enabled, like:
+
+\starttyping
+\enabletrackers[xml.show,xml.parse]
+\stoptyping
+
+The full list (currently) is:
+
+\starttabulate[|lT|p|]
+\NC xml.entities \NC show what entities are seen and replaced \NC \NR
+\NC xml.path \NC show the result of parsing an lpath expression \NC \NR
+\NC xml.parse \NC show stepwise resolving of expressions \NC \NR
+\NC xml.profile \NC report all parsed lpath expressions (in the log) \NC \NR
+\NC xml.remap \NC show what namespaces are remapped \NC \NR
+\NC lxml.access \NC report errors with respect to resolving (symbolic) nodes \NC \NR
+\NC lxml.comments \NC show the comments that are encountered (if at all) \NC \NR
+\NC lxml.loading \NC show what files are loaded and converted \NC \NR
+\NC lxml.setups \NC show what setups are being associated to elements \NC \NR
+\stoptabulate
+
+In one of our workflows we produce books from \XML\ where the (educational)
+content is organized in many small files. Each book has about 5~chapters and each
+chapter is made of sections that contain text, exercises, resources, etc.\ and so
+the document is assembled from thousands of files (don't worry, runtime inclusion
+is pretty fast). In order to see where in the sources content resides we can
+trace the filename.
+
+\startxmlcmd {\cmdbasicsetup{xmlinclusion}}
+ returns the file where the node comes from
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlinclusions}}
+ returns the list of files where the node comes from
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlbadinclusions}}
+ returns a list of files that were not included due to some problem
+\stopxmlcmd
+
+Of course you have to make sure that these names end up somewhere visible, for
+instance in the margin.
+
+\stopsection
+
+\startsection[title={expansion}]
+
+For novice users the concept of expansion might sound frightening and to some
+extend it is. However, it is important enough to spend some words on it here.
+
+It is good to realize that most setups are sort of immediate. When one setup is
+issued, it can call another one and so on. Normally you won't notice that but
+there are cases where that can be a problem. In \TEX\ you can define a macro,
+take for instance:
+
+\starttyping
+\startxmlsetups xml:foo
+ \def\foobar{\xmlfirst{#1}{/bar}}
+\stopxmlsetups
+\stoptyping
+
+you store the reference top node \type {bar} in \type {\foobar} maybe for later use. In
+this case the content is not yet fetched, it will be done when \type {\foobar} is
+called.
+
+\starttyping
+\startxmlsetups xml:foo
+ \edef\foobar{\xmlfirst{#1}{/bar}}
+\stopxmlsetups
+\stoptyping
+
+Here the content of \type {bar} becomes the body of the macro. But what if
+\type {bar} itself contains elements that also contain elements. When there
+is a setup for \type {bar} it will be triggered and so on.
+
+When that setup looks like:
+
+\starttyping
+\startxmlsetups xml:bar
+ \def\barfoo{\xmlflush{#1}}
+\stopxmlsetups
+\stoptyping
+
+Here we get something like:
+
+\starttyping
+\foobar => {\def\barfoo{...}}
+\stoptyping
+
+When \type {\barfoo} is not defined we get an error and when it is known and expands
+to something weird we might also get an error.
+
+Especially when you don't know what content can show up, this can result in errors
+when an expansion fails, for example because some macro being used is not defined.
+To prevent this we can define a macro:
+
+\starttyping
+\starttexdefinition unexpanded xml:bar:macro #1
+ \def\barfoo{\xmlflush{#1}}
+\stoptexdefinition
+
+\startxmlsetups xml:bar
+ \texdefinition{xml:bar:macro}{#1}
+\stopxmlsetups
+\stoptyping
+
+The setup \type {xml:bar} will still expand but the replacement text now is just the
+call to the macro, think of:
+
+\starttyping
+\foobar => {\texdefinition{xml:bar:macro}{#1}}
+\stoptyping
+
+But this is often not needed, most \CONTEXT\ commands can handle the expansions
+quite well but it's good to know that there is a way out. So, now to some
+examples. Imagine that we have an \XML\ file that looks as follows:
+
+\starttyping
+<?xml version='1.0' ?>
+<demo>
+ <chapter>
+ <title>Some <em>short</em> title</title>
+ <content>
+ zeta
+ <index>
+ <key>zeta</key>
+ <content>zeta again</content>
+ </index>
+ alpha
+ <index>
+ <key>alpha</key>
+ <content>alpha <em>again</em></content>
+ </index>
+ gamma
+ <index>
+ <key>gamma</key>
+ <content>gamma</content>
+ </index>
+ beta
+ <index>
+ <key>beta</key>
+ <content>beta</content>
+ </index>
+ delta
+ <index>
+ <key>delta</key>
+ <content>delta</content>
+ </index>
+ done!
+ </content>
+ </chapter>
+</demo>
+\stoptyping
+
+There are a few structure related elements here: a chapter (with its list entry)
+and some index entries. Both are multipass related and therefore travel around.
+This means that when we let data end up in the auxiliary file, we need to make
+sure that we end up with either expanded data (i.e.\ no references to the \XML\
+tree) or with robust forward and backward references to elements in the tree.
+
+Here we discuss three approaches (and more may show up later): pushing \XML\ into
+the auxiliary file and using references to elements either or not with an
+associated setup. We control the variants with a switch.
+
+\starttyping
+\newcount\TestMode
+
+\TestMode=0 % expansion=xml
+\TestMode=1 % expansion=yes, index, setup
+\TestMode=2 % expansion=yes
+\stoptyping
+
+We apply a couple of setups:
+
+\starttyping
+\startxmlsetups xml:mysetups
+ \xmlsetsetup{\xmldocument}{demo|index|content|chapter|title|em}{xml:*}
+\stopxmlsetups
+
+\xmlregistersetup{xml:mysetups}
+\stoptyping
+
+The main document is processed with:
+
+\starttyping
+\startxmlsetups xml:demo
+ \xmlflush{#1}
+ \subject{contents}
+ \placelist[chapter][criterium=all]
+ \subject{index}
+ \placeregister[index][criterium=all]
+ \page % else buffer is forgotten when placing header
+\stopxmlsetups
+\stoptyping
+
+First we show three alternative ways to deal with the chapter. The first case
+expands the \XML\ reference so that we have an \XML\ stream in the auxiliary
+file. This stream is processed as a small independent subfile when needed. The
+second case registers a reference to the current element (\type {#1}). This means
+that we have access to all data of this element, like attributes, title and
+content. What happens depends on the given setup. The third variant does the same
+but here the setup is part of the reference.
+
+\starttyping
+\startxmlsetups xml:chapter
+ \ifcase \TestMode
+ % xml code travels around
+ \setuphead[chapter][expansion=xml]
+ \startchapter[title=eh: \xmltext{#1}{title}]
+ \xmlfirst{#1}{content}
+ \stopchapter
+ \or
+ % index is used for access via setup
+ \setuphead[chapter][expansion=yes,xmlsetup=xml:title:flush]
+ \startchapter[title=\xmlgetindex{#1}]
+ \xmlfirst{#1}{content}
+ \stopchapter
+ \or
+ % tex call to xml using index is used
+ \setuphead[chapter][expansion=yes]
+ \startchapter[title=hm: \xmlreference{#1}{xml:title:flush}]
+ \xmlfirst{#1}{content}
+ \stopchapter
+ \fi
+\stopxmlsetups
+
+\startxmlsetups xml:title:flush
+ \xmltext{#1}{title}
+\stopxmlsetups
+\stoptyping
+
+We need to deal with emphasis and the content of the chapter.
+
+\starttyping
+\startxmlsetups xml:em
+ \begingroup\em\xmlflush{#1}\endgroup
+\stopxmlsetups
+
+\startxmlsetups xml:content
+ \xmlflush{#1}
+\stopxmlsetups
+\stoptyping
+
+A similar approach is followed with the index entries. Watch how we use the
+numbered entries variant (in this case we could also have used just \type
+{entries} and \type {keys}).
+
+\starttyping
+\startxmlsetups xml:index
+ \ifcase \TestMode
+ \setupregister[index][expansion=xml,xmlsetup=]
+ \setstructurepageregister
+ [index]
+ [entries:1=\xmlfirst{#1}{content},
+ keys:1=\xmltext{#1}{key}]
+ \or
+ \setupregister[index][expansion=yes,xmlsetup=xml:index:flush]
+ \setstructurepageregister
+ [index]
+ [entries:1=\xmlgetindex{#1},
+ keys:1=\xmltext{#1}{key}]
+ \or
+ \setupregister[index][expansion=yes,xmlsetup=]
+ \setstructurepageregister
+ [index]
+ [entries:1=\xmlreference{#1}{xml:index:flush},
+ keys:1=\xmltext{#1}{key}]
+ \fi
+\stopxmlsetups
+
+\startxmlsetups xml:index:flush
+ \xmlfirst{#1}{content}
+\stopxmlsetups
+\stoptyping
+
+Instead of this flush, you can use the predefined setup \type {xml:flush}
+unless it is overloaded by you.
+
+The file is processed by:
+
+\starttyping
+\starttext
+ \xmlprocessfile{main}{test.xml}{}
+\stoptext
+\stoptyping
+
+We don't show the result here. If you're curious what the output is, you can test
+it yourself. In that case it also makes sense to peek into the \type {test.tuc}
+file to see how the information travels around. The \type {metadata} fields carry
+information about how to process the data.
+
+The first case, the \XML\ expansion one, is somewhat special in the sense that
+internally we use small pseudo files. You can control the rendering by tweaking
+the following setups:
+
+\starttyping
+\startxmlsetups xml:ctx:sectionentry
+ \xmlflush{#1}
+\stopxmlsetups
+
+\startxmlsetups xml:ctx:registerentry
+ \xmlflush{#1}
+\stopxmlsetups
+\stoptyping
+
+{\em When these methods work out okay the other structural elements will be
+dealt with in a similar way.}
+
+\stopsection
+
+\startsection[title={special cases}]
+
+Normally the content will be flushed under a special (so called) catcode regime.
+This means that characters that have a special meaning in \TEX\ will have no such
+meaning in an \XML\ file. If you want content to be treated as \TEX\ code, you can
+use one of the following:
+
+\startxmlcmd {\cmdbasicsetup{xmlflushcontext}}
+ flush the given \cmdinternal {cd:node} using the \TEX\ character
+ interpretation scheme
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlcontext}}
+ flush the match of \cmdinternal {cd:lpath} for the given \cmdinternal
+ {cd:node} using the \TEX\ character interpretation scheme
+\stopxmlcmd
+
+We use this in cases like:
+
+\starttyping
+....
+ \xmlsetsetup {#1} {
+ tm|texformula|
+ } {xml:*}
+....
+
+\startxmlsetups xml:tm
+ \mathematics{\xmlflushcontext{#1}}
+\stopxmlsetups
+
+\startxmlsetups xml:texformula
+ \placeformula\startformula\xmlflushcontext{#1}\stopformula
+\stopxmlsetups
+\stoptyping
+
+\stopsection
+
+\startsection[title={collecting}]
+
+Say that your document has
+
+\starttyping
+<table>
+ <tr>
+ <td>foo</td>
+ <td>bar<td>
+ </tr>
+</table>
+\stoptyping
+
+And that you need to convert that to \TEX\ speak like:
+
+\starttyping
+\bTABLE
+ \bTR
+ \bTD foo \eTD
+ \bTD bar \eTD
+ \eTR
+\eTABLE
+\stoptyping
+
+A simple mapping is:
+
+\starttyping
+\startxmlsetups xml:table
+ \bTABLE \xmlflush{#1} \eTABLE
+\stopxmlsetups
+\startxmlsetups xml:tr
+ \bTR \xmlflush{#1} \eTR
+\stopxmlsetups
+\startxmlsetups xml:td
+ \bTD \xmlflush{#1} \eTD
+\stopxmlsetups
+\stoptyping
+
+The \type {\bTD} command is a so called delimited command which means that it
+picks up its argument by looking for an \type {\eTD}. For the simple case here
+this works quite well because the flush is inside the pair. This is not the case
+in the following variant:
+
+\starttyping
+\startxmlsetups xml:td:start
+ \bTD
+\stopxmlsetups
+\startxmlsetups xml:td:stop
+ \eTD
+\stopxmlsetups
+\startxmlsetups xml:td
+ \xmlsetup{#1}{xml:td:start}
+ \xmlflush{#1}
+ \xmlsetup{#1}{xml:td:stop}
+\stopxmlsetups
+\stoptyping
+
+When for some reason \TEX\ gets confused you can revert to a mechanism that
+collects content.
+
+\starttyping
+\startxmlsetups xml:td:start
+ \startcollect
+ \bTD
+ \stopcollect
+\stopxmlsetups
+\startxmlsetups xml:td:stop
+ \startcollect
+ \eTD
+ \stopcollect
+\stopxmlsetups
+\startxmlsetups xml:td
+ \startcollecting
+ \xmlsetup{#1}{xml:td:start}
+ \xmlflush{#1}
+ \xmlsetup{#1}{xml:td:stop}
+ \stopcollecting
+\stopxmlsetups
+\stoptyping
+
+You can even implement solutions that effectively do this:
+
+\starttyping
+\startcollecting
+ \startcollect \bTABLE \stopcollect
+ \startcollect \bTR \stopcollect
+ \startcollect \bTD \stopcollect
+ \startcollect foo\stopcollect
+ \startcollect \eTD \stopcollect
+ \startcollect \bTD \stopcollect
+ \startcollect bar\stopcollect
+ \startcollect \eTD \stopcollect
+ \startcollect \eTR \stopcollect
+ \startcollect \eTABLE \stopcollect
+\stopcollecting
+\stoptyping
+
+Of course you only need to go that complex when the situation demands it. Here is
+another weird one:
+
+\starttyping
+\startcollecting
+ \startcollect \setupsomething[\stopcollect
+ \startcollect foo=\stopcollect
+ \startcollect FOO,\stopcollect
+ \startcollect bar=\stopcollect
+ \startcollect BAR,\stopcollect
+ \startcollect ]\stopcollect
+\stopcollecting
+\stoptyping
+
+\stopsection
+
+\startsection[title={selectors and injectors}]
+
+This section describes a bit special feature, one that we needed for a project
+where we could not touch the original content but could add specific sections for
+our own purpose. Hopefully the example demonstrates its useability.
+
+\enabletrackers[lxml.selectors]
+
+\startbuffer[foo]
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?context-directive message info 1: this is a demo file ?>
+<?context-message-directive info 2: this is a demo file ?>
+
+<one>
+ <two>
+ <?context-select begin t1 t2 t3 ?>
+ <three>
+ t1 t2 t3
+ <?context-directive injector crlf t1 ?>
+ t1 t2 t3
+ </three>
+ <?context-select end ?>
+ <?context-select begin t4 ?>
+ <four>
+ t4
+ </four>
+ <?context-select end ?>
+ <?context-select begin t8 ?>
+ <four>
+ t8.0
+ t8.0
+ </four>
+ <?context-select end ?>
+ <?context-include begin t4 ?>
+ <!--
+ <three>
+ t4.t3
+ <?context-directive injector crlf t1 ?>
+ t4.t3
+ </three>
+ -->
+ <three>
+ t3
+ <?context-directive injector crlf t1 ?>
+ t3
+ </three>
+ <?context-include end ?>
+ <?context-select begin t8 ?>
+ <four>
+ t8.1
+ t8.1
+ </four>
+ <?context-select end ?>
+ <?context-select begin t8 ?>
+ <four>
+ t8.2
+ t8.2
+ </four>
+ <?context-select end ?>
+ <?context-select begin t4 ?>
+ <four>
+ t4
+ t4
+ </four>
+ <?context-select end ?>
+ <?context-directive injector page t7 t8 ?>
+ foo
+ <?context-directive injector blank t1 ?>
+ bar
+ <?context-directive injector page t7 t8 ?>
+ bar
+ </two>
+</one>
+\stopbuffer
+
+\typebuffer[foo]
+
+First we show how to plug in a directive. Processing instructions like the
+following are normally ignored by an \XML\ processor, unless they make sense
+to it.
+
+\starttyping
+<?context-directive message info 1: this is a demo file ?>
+<?context-message-directive info 2: this is a demo file ?>
+\stoptyping
+
+We can define a message handler as follows:
+
+\startbuffer
+\def\MyMessage#1#2#3{\writestatus{#1}{#2 #3}}
+
+\xmlinstalldirective{message}{MyMessage}
+\stopbuffer
+
+\typebuffer \getbuffer
+
+When this file is processed you will see this on the console:
+
+\starttyping
+info > 1: this is a demo file
+info > 2: this is a demo file
+\stoptyping
+
+The file has some sections that can be used or ignored. The recipe for
+obeying \type {t1} and \type {t4} is the following:
+
+\startbuffer
+\xmlsetinjectors[t1]
+\xmlsetinjectors[t4]
+
+\startxmlsetups xml:initialize
+ \xmlapplyselectors{#1}
+ \xmlsetsetup {#1} {
+ one|two|three|four
+ } {xml:*}
+\stopxmlsetups
+
+\xmlregistersetup{xml:initialize}
+
+\startxmlsetups xml:one
+ [ONE \xmlflush{#1} ONE]
+\stopxmlsetups
+
+\startxmlsetups xml:two
+ [TWO \xmlflush{#1} TWO]
+\stopxmlsetups
+
+\startxmlsetups xml:three
+ [THREE \xmlflush{#1} THREE]
+\stopxmlsetups
+
+\startxmlsetups xml:four
+ [FOUR \xmlflush{#1} FOUR]
+\stopxmlsetups
+\stopbuffer
+
+\typebuffer \getbuffer
+
+This typesets:
+
+\startnarrower
+\xmlprocessbuffer{main}{foo}{}
+\stopnarrower
+
+The include coding is kind of special: it permits adding content (in a comment)
+and ignoring the rest so that we indeed can add something without interfering
+with the original. Of course in a normal workflow such messy solutions are
+not needed, but alas, often workflows are not that clean, especially when one
+has no real control over the source.
+
+\startxmlcmd {\cmdbasicsetup{xmlsetinjectors}}
+ enables a list of injectors that will be used
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlresetinjectors}}
+ resets the list of injectors
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlinjector}}
+ expands an injection (command); normally this one is only used
+ (in some setup) or for testing
+\stopxmlcmd
+
+\startxmlcmd {\cmdbasicsetup{xmlapplyselectors}}
+ analyze the tree \cmdinternal {cd:node} for marked sections that
+ will be injected
+\stopxmlcmd
+
+We have some injections predefined:
+
+\starttyping
+\startsetups xml:directive:injector:page
+ \page
+\stopsetups
+
+\startsetups xml:directive:injector:column
+ \column
+\stopsetups
+
+\startsetups xml:directive:injector:blank
+ \blank
+\stopsetups
+\stoptyping
+
+In the example we see:
+
+\starttyping
+<?context-directive injector page t7 t8 ?>
+\stoptyping
+
+When we set \type {\xmlsetinjector[t7]} a pagebreak will injected in that spot.
+Tags like \type {t7}, \type {t8} etc.\ can represent versions.
+
+\stopsection
+
+\startsection[title=preprocessing]
+
+% local match = lpeg.match
+% local replacer = lpeg.replacer("BAD TITLE:","<bold>BAD TITLE:</bold>")
+%
+% function lxml.preprocessor(data,settings)
+% return match(replacer,data)
+% end
+
+\startbuffer[pre-code]
+\startluacode
+ function lxml.preprocessor(data,settings)
+ return string.find(data,"BAD TITLE:")
+ and string.gsub(data,"BAD TITLE:","<bold>BAD TITLE:</bold>")
+ or data
+ end
+\stopluacode
+\stopbuffer
+
+\startbuffer[pre-xml]
+\startxmlsetups pre:demo:initialize
+ \xmlsetsetup{#1}{*}{pre:demo:*}
+\stopxmlsetups
+
+\xmlregisterdocumentsetup{pre:demo}{pre:demo:initialize}
+
+\startxmlsetups pre:demo:root
+ \xmlflush{#1}
+\stopxmlsetups
+
+\startxmlsetups pre:demo:bold
+ \begingroup\bf\xmlflush{#1}\endgroup
+\stopxmlsetups
+
+\starttext
+ \xmlprocessbuffer{pre:demo}{demo}{}
+\stoptext
+\stopbuffer
+
+Say that you have the following \XML\ setup:
+
+\typebuffer[pre-xml]
+
+and that (such things happen) the input looks like this:
+
+\startbuffer[demo]
+<root>
+BAD TITLE: crap crap crap ...
+
+BAD TITLE: crap crap crap ...
+</root>
+\stopbuffer
+
+\typebuffer[demo]
+
+You can then clean up these \type {BAD TITLE}'s as follows:
+
+\typebuffer[pre-code]
+
+and get as result:
+
+\start \getbuffer[pre-code,pre-xml] \stop
+
+The preprocessor function gets as second argument the current settings, an d
+the field \type {currentresource} can be used to limit the actions to
+specific resources, in our case it's \type {buffer: demo}. Afterwards you can
+reset the proprocessor with:
+
+\startluacode
+lxml.preprocessor = nil
+\stopluacode
+
+Future versions might give some more control over preprocessors. For now consider
+it to be a quick hack.
+
+\stopsection
+
+\stopchapter
+
+\stopcomponent
diff --git a/doc/context/sources/general/manuals/xml/xml-mkiv.tex b/doc/context/sources/general/manuals/xml/xml-mkiv.tex
index 37f321646..77054e79c 100644
--- a/doc/context/sources/general/manuals/xml/xml-mkiv.tex
+++ b/doc/context/sources/general/manuals/xml/xml-mkiv.tex
@@ -31,4385 +31,25 @@
%
% \xmldirect
-\input lxml-ctx.mkiv
-
-\settrue \xmllshowtitle
-\setfalse\xmllshowwarning
-
-\usemodule[set-11]
-
-\loadsetups[i-context]
-
-% \definehspace[squad][1em plus .25em minus .25em]
-
-\usemodule[abr-02]
-
-\setuplayout
- [location=middle,
- marking=on,
- backspace=20mm,
- cutspace=20mm,
- topspace=15mm,
- header=15mm,
- footer=15mm,
- height=middle,
- width=middle]
-
-\setuppagenumbering
- [alternative=doublesided,
- location=]
-
-\setupfootertexts
- [][pagenumber]
-
-\setupheadertexts
- [][chapter]
-
-\setupheader
- [color=colortwo,
- style=bold]
-
-\setupfooter
- [color=colortwo,
- style=bold]
-
-\setuphead
- [chapter]
- [page={yes,header,right},
- header=empty,
- style=\bfc]
-
-\setupsectionblock
- [page={yes,header,right}]
-
-\starttexdefinition unexpanded section:chapter:number #1
- \doifmode{*sectionnumber} {
- \bf
- \llap{<\enspace}#1\enspace>
- }
-\stoptexdefinition
-
-\starttexdefinition unexpanded section:section:number #1
- \doifmode{*sectionnumber} {
- \bf
- \llap{<<\enspace}#1\enspace>>
- }
-\stoptexdefinition
-
-\starttexdefinition unexpanded section:subsection:number #1
- \doifmode{*sectionnumber} {
- \bf
- \llap{<<<\enspace}#1\enspace>>>
- }
-\stoptexdefinition
-
-\setuphead[chapter] [numbercolor=black,numbercommand=\texdefinition{section:chapter:number}]
-\setuphead[section] [numbercolor=black,numbercommand=\texdefinition{section:section:number}]
-\setuphead[subsection][numbercolor=black,numbercommand=\texdefinition{section:subsection:number}]
-
-\setuphead
- [section]
- [style=\bfa]
-
-\setuplist
- [chapter]
- [style=bold]
-
-\setupinteractionscreen
- [option=doublesided]
-
-\setupalign
- [tolerant,stretch]
-
-\setupwhitespace
- [big]
-
-\setuptolerance
- [tolerant]
-
-\doifelsemode {atpragma} {
- \setupbodyfont[lucidaot,10pt]
-} {
- \setupbodyfont[dejavu,10pt]
-}
-
-\definecolor[colorone] [b=.5]
-\definecolor[colortwo] [s=.3]
-\definecolor[colorthree][y=.5]
-
-\setuptype
- [color=colorone]
-
-\setuptyping
- [color=colorone]
-
-\setuphead
- [lshowtitle]
- [style=\tt,
- color=colorone]
-
-\setuphead
- [chapter,section]
- [numbercolor=colortwo,
- color=colorone]
-
-\definedescription
- [xmlcmd]
- [alternative=hanging,
- width=line,
- distance=1em,
- margin=2em,
- headstyle=monobold,
- headcolor=colorone]
-
-\setupframedtext
- [setuptext]
- [framecolor=colorone,
- rulethickness=1pt,
- corner=round]
-
-\usemodule[punk]
-
-\usetypescript[punk]
-
-\definelayer
- [page]
- [width=\paperwidth,
- height=\paperheight]
+\environment xml-mkiv-style
\starttext
-\setuplayout[page]
-
-\startstandardmakeup
- \startfontclass[none] % nil the current fontclass since it may append its features
- \EnableRandomPunk
- \setlayerframed
- [page]
- [width=\paperwidth,height=\paperheight,
- background=color,backgroundcolor=colorone,backgroundoffset=1ex,frame=off]
- {}
- \definedfont[demo@punk at 18pt]
- \setbox\scratchbox\vbox {
- \hsize\dimexpr\paperwidth+2ex\relax
- \setupinterlinespace
- \baselineskip 1\baselineskip plus 1pt minus 1pt
- \raggedcenter
- \color[colortwo]{\dorecurse{1000}{XML }}
- }
- \setlayer
- [page]
- [preset=middle]
- {\vsplit\scratchbox to \dimexpr\paperheight+2ex\relax}
- \definedfont[demo@punk at 90pt]
- \setstrut
- \setlayerframed
- [page]
- [preset=rightbottom,offset=10mm]
- [foregroundcolor=colorthree,align=flushright,offset=overlay,frame=off]
- {Dealing\\with XML in\\Con\TeX t MkIV}
- \definedfont[demo@punk at 18pt]
- \setstrut
- \setlayerframed
- [page]
- [preset=righttop,offset=10mm,x=3mm,rotation=90]
- [foregroundcolor=colorthree,align=flushright,offset=overlay,frame=off]
- {Hans Hagen, Pragma ADE, \currentdate}
- \tightlayer[page]
- \stopfontclass
-\stopstandardmakeup
-
-\setuplayout
+\component xml-mkiv-titlepage
\startfrontmatter
-
-\starttitle[title=Contents]
-
-\placelist
- [chapter,section]
-
-\stoptitle
-
-\startchapter[title={Introduction}]
-
-This manual presents the \MKIV\ way of dealing with \XML. Although the
-traditional \MKII\ streaming parser has a charming simplicity in its control, for
-complex documents the tree based \MKIV\ method is more convenient. It is for this
-reason that the old method has been removed from \MKIV. If you are familiar with
-\XML\ processing in \MKII, then you will have noticed that the \MKII\ commands
-have \type {XML} in their name. The \MKIV\ commands have a lowercase \type {xml}
-in their names. That way there is no danger for confusion or a mixup.
-
-You may wonder why we do these manipulations in \TEX\ and not use \XSLT\ (or
-other transformation methods) instead. The advantage of an integrated approach is
-that it simplifies usage. Think of not only processing the document, but also
-using \XML\ for managing resources in the same run. An \XSLT\ approach is just as
-verbose (after all, you still need to produce \TEX\ code) and probably less
-readable. In the case of \MKIV\ the integrated approach is also faster and gives
-us the option to manipulate content at runtime using \LUA. It has the additional
-advantage that to some extend we can handle a mix of \TEX\ and \XML\ because we
-know when we're doing one or the other.
-
-This manual is dedicated to Taco Hoekwater, one of the first \CONTEXT\ users, and
-also the first to use it for processing \XML. Who could have thought at that time
-that we would have a more convenient way of dealing with those angle brackets.
-The second version for this manual is dedicated to Thomas Schmitz, a power user
-who occasionally became victim of the evolving mechanisms.
-
-\blank
-
-\startlines
-Hans Hagen
-\PRAGMA
-Hasselt NL
-2008\endash2016
-\stoplines
-
-\stopchapter
-
+ \component xml-mkiv-contents
+ \component xml-mkiv-introduction
\stopfrontmatter
\startbodymatter
-
-\startchapter[title={Setting up a converter}]
-
-\startsection[title={from structure to setup}]
-
-We use a very simple document structure for demonstrating how a converter is
-defined. In practice a mapping will be more complex, especially when we have a
-style with complex chapter openings using data coming from all kind of places,
-different styling of sections with the same name, selectively (out of order)
-flushed content, special formatting, etc.
-
-\typefile{manual-demo-1.xml}
-
-Say that this document is stored in the file \type {demo.xml}, then the following
-code can be used as starting point:
-
-\starttyping
-\startxmlsetups xml:demo:base
- \xmlsetsetup{#1}{document|section|p}{xml:demo:*}
-\stopxmlsetups
-
-\xmlregisterdocumentsetup{demo}{xml:demo:base}
-
-\startxmlsetups xml:demo:document
- \starttitle[title={Contents}]
- \placelist[chapter]
- \stoptitle
- \xmlflush{#1}
-\stopxmlsetups
-
-\startxmlsetups xml:demo:section
- \startchapter[title=\xmlfirst{#1}{/title}]
- \xmlfirst{#1}{/content}
- \stopchapter
-\stopxmlsetups
-
-\startxmlsetups xml:demo:p
- \xmlflush{#1}\endgraf
-\stopxmlsetups
-
-\xmlprocessfile{demo}{demo.xml}{}
-\stoptyping
-
-Watch out! These are not just setups, but specific \XML\ setups which get an
-argument passed (the \type {#1}). If for some reason your \XML\ processing fails,
-it might be that you mistakenly have used a normal setup definition. The argument
-\type {#1} represents the current node (element) and is a unique identifier. For
-instance a \type {<p>..</p>} can have an identifier {demo::5}. So, we can get
-something:
-
-\starttyping
-\xmlflush{demo::5}\endgraf
-\stoptyping
-
-but as well:
-
-\starttyping
-\xmlflush{demo::6}\endgraf
-\stoptyping
-
-Keep in mind that the references tor the actual nodes (elements) are
-abstractions, you never see those \type {<id>::<number>}'s, because we will use
-either the abstract \type {#1} (any node) or an explicit reference like \type
-{demo}. The previous setup when issued will be like:
-
-\starttyping
-\startchapter[title=\xmlfirst{demo::3}{/title}]
- \xmlfirst{demo::4}{/content}
-\stopchapter
-\stoptyping
-
-Here the \type {title} is used to typeset the chapter title but also for an entry
-in the table of contents. At the moment the title is typeset the \XML\ node gets
-looked up and expanded in real text. However, for the list it gets stored for
-later use. One can argue that this is not needed for \XML, because one can just
-filter all the titles and use page references, but then one also looses the
-control one normally has over such titles. For instance it can be that some
-titles are rendered differently and for that we need to keep track of usage.
-Doing that with transformations or filtering is often more complex than leaving
-that to \TEX. As soon as the list gets typeset, the reference (\type {demo::#3})
-is used for the lookup. This is because by default the title is stored as given.
-So, as long as we make sure the \XML\ source is loaded before the table of
-contents is typeset we're ok. Later we will look into this in more detail, for
-now it's enough to know that in most cases the abstract \type {#1} reference will
-work out ok.
-
-Contrary to the style definitions this interface looks rather low level (with no
-optional arguments) and the main reason for this is that we want processing to be
-fast. So, the basic framework is:
-
-\starttyping
-\startxmlsetups xml:demo:base
- % associate setups with elements
-\stopxmlsetups
-
-\xmlregisterdocumentsetup{demo}{xml:demo:base}
-
-% define setups for matches
-
-\xmlprocessfile{demo}{demo.xml}{}
-\stoptyping
-
-In this example we mostly just flush the content of an element and in the case of
-a section we flush explicit child elements. The \type {#1} in the example code
-represents the current element. The line:
-
-\starttyping
-\xmlsetsetup{demo}{*}{-}
-\stoptyping
-
-sets the default for each element to \quote {just ignore it}. A \type {+} would
-make the default to always flush the content. This means that at this point we
-only handle:
-
-\starttyping
-<section>
- <title>Some title</title>
- <content>
- <p>a paragraph of text</p>
- </content>
-</section>
-\stoptyping
-
-In the next section we will deal with the slightly more complex itemize and
-figure placement. At first sight all these setups may look overkill but keep in
-mind that normally the number of elements is rather limited. The complexity is
-often in the style and having access to each snippet of content is actually
-quite handy for that.
-
-\stopsection
-
-\startsection[title={alternative solutions}]
-
-Dealing with an itemize is rather simple (as long as we forget about
-attributes that control the behaviour):
-
-\starttyping
-<itemize>
- <item>first</item>
- <item>second</item>
-</itemize>
-\stoptyping
-
-First we need to add \type {itemize} to the setup assignment (unless we've used
-the wildcard \type {*}):
-
-\starttyping
-\xmlsetsetup{demo}{document|section|p|itemize}{xml:demo:*}
-\stoptyping
-
-The setup can look like:
-
-\starttyping
-\startxmlsetups xml:demo:itemize
- \startitemize
- \xmlfilter{#1}{/item/command(xml:demo:itemize:item)}
- \stopitemize
-\stopxmlsetups
-
-\startxmlsetups xml:demo:itemize:item
- \startitem
- \xmlflush{#1}
- \stopitem
-\stopxmlsetups
-\stoptyping
-
-An alternative is to map item directly:
-
-\starttyping
-\xmlsetsetup{demo}{document|section|p|itemize|item}{xml:demo:*}
-\stoptyping
-
-and use:
-
-\starttyping
-\startxmlsetups xml:demo:itemize
- \startitemize
- \xmlflush{#1}
- \stopitemize
-\stopxmlsetups
-
-\startxmlsetups xml:demo:item
- \startitem
- \xmlflush{#1}
- \stopitem
-\stopxmlsetups
-\stoptyping
-
-Sometimes, a more local solution using filters and \type {/command(...)} makes more
-sense, especially when the \type {item} tag is used for other purposes as well.
-
-Explicit flushing with \type {command} is definitely the way to go when you have
-complex products. In one of our projects we compose math school books from many
-thousands of small \XML\ files, and from one source set several products are
-typeset. Within a book sections get done differently, content gets used, ignored
-or interpreted differently depending on the kind of content, so there is a
-constant checking of attributes that drive the rendering. In that a generic setup
-for a title element makes less sense than explicit ones for each case. (We're
-talking of huge amounts of files here, including multiple images on each rendered
-page.)
-
-When using \type {command} you can pass two arguments, the first is the setup for
-the match, the second one for the miss, as in:
-
-\starttyping
-\xmlfilter{#1}{/element/command(xml:true,xml:false)}
-\stoptyping
-
-Back to the example, this leaves us with dealing with the resources, like
-figures:
-
-\starttyping
-<resource type='figure'>
- <caption>A picture of a cow.</caption>
- <content><external file="cow.pdf"/></content>
-</resource>
-\stoptyping
-
-Here we can use a more restricted match:
-
-\starttyping
-\xmlsetsetup{demo}{resource[@type='figure']}{xml:demo:figure}
-\xmlsetsetup{demo}{external}{xml:demo:*}
-\stoptyping
-
-and the definitions:
-
-\starttyping
-\startxmlsetups xml:demo:figure
- \placefigure
- {\xmlfirst{#1}{/caption}}
- {\xmlfirst{#1}{/content}}
-\stopxmlsetups
-
-\startxmlsetups xml:demo:external
- \externalfigure[\xmlatt{#1}{file}]
-\stopxmlsetups
-\stoptyping
-
-At this point it is good to notice that \type {\xmlatt{#1}{file}} is passed as it
-is: a macro call. This means that when a macro like \type {\externalfigure} uses
-the first argument frequently without first storing its value, the lookup is done
-several times. A solution for this is:
-
-\starttyping
-\startxmlsetups xml:demo:external
- \expanded{\externalfigure[\xmlatt{#1}{file}]}
-\stopxmlsetups
-\stoptyping
-
-Because the lookup is rather fast, normally there is no need to bother about this
-too much because internally \CONTEXT\ already makes sure such expansion happens
-only once.
-
-An alternative definition for placement is the following:
-
-\starttyping
-\xmlsetsetup{demo}{resource}{xml:demo:resource}
-\stoptyping
-
-with:
-
-\starttyping
-\startxmlsetups xml:demo:resource
- \placefloat
- [\xmlatt{#1}{type}]
- {\xmlfirst{#1}{/caption}}
- {\xmlfirst{#1}{/content}}
-\stopxmlsetups
-\stoptyping
-
-This way you can specify \type {table} as type too. Because you can define your
-own float types, more complex variants are also possible. In that case it makes
-sense to provide some default behaviour too:
-
-\starttyping
-\definefloat[figure-here][figure][default=here]
-\definefloat[figure-left][figure][default=left]
-\definefloat[table-here] [table] [default=here]
-\definefloat[table-left] [table] [default=left]
-
-\startxmlsetups xml:demo:resource
- \placefloat
- [\xmlattdef{#1}{type}{figure}-\xmlattdef{#1}{location}{here}]
- {\xmlfirst{#1}{/caption}}
- {\xmlfirst{#1}{/content}}
-\stopxmlsetups
-\stoptyping
-
-In this example we support two types and two locations. We default to a figure
-placed (when possible) at the current location.
-
-\stopsection
-
-\stopchapter
-
-\startchapter[title={Filtering content}]
-
-\startsection[title={\TEX\ versus \LUA}]
-
-It will not come as a surprise that we can access \XML\ files from \TEX\ as well
-as from \LUA. In fact there are two methods to deal with \XML\ in \LUA. First
-there are the low level \XML\ functions in the \type {xml} namespace. On top of
-those functions there is a set of functions in the \type {lxml} namespace that
-deals with \XML\ in a more \TEX ie way. Most of these have similar commands at
-the \TEX\ end.
-
-\startbuffer
-\startxmlsetups first:demo:one
- \xmlfilter {#1} {artist/name[text()='Randy Newman']/..
- /albums/album[position()=3]/command(first:demo:two)}
-\stopxmlsetups
-
-\startxmlsetups first:demo:two
- \blank \start \tt
- \xmldisplayverbatim{#1}
- \stop \blank
-\stopxmlsetups
-
-\xmlprocessfile{demo}{music-collection.xml}{first:demo:one}
-\stopbuffer
-
-\typebuffer
-
-This gives the following snippet of verbatim \XML\ code. The indentation is
-conform the indentation in the whole \XML\ file. \footnote {The (probably
-outdated) \XML\ file contains the collection stores on my slimserver instance.
-You can use the \type {mtxrun --script flac} to generate such files.}
-
-\doifmodeelse {atpragma} {
- \getbuffer
-} {
- \typefile{xml-mkiv-01.xml}
-}
-
-An alternative written in \LUA\ looks as follows:
-
-\startbuffer
-\blank \start \tt \startluacode
- local m = lxml.load("mine","music-collection.xml") -- m == lxml.id("mine")
- local p = "artist/name[text()='Randy Newman']/../albums/album[position()=4]"
- local l = lxml.filter(m,p) -- returns a list (with one entry)
- lxml.displayverbatim(l[1])
-\stopluacode \stop \blank
-\stopbuffer
-
-\typebuffer
-
-This produces:
-
-\doifmodeelse {atpragma} {
- \getbuffer
-} {
- \typefile{xml-mkiv-02.xml}
-}
-
-You can use both methods mixed but in practice we will use the \TEX\ commands in
-regular styles and the mixture in modules, for instance in those dealing with
-\MATHML\ and cals tables. For complex matters you can write your own finalizers
-(the last action to be taken in a match) in \LUA\ and use them at the \TEX\ end.
-
-\stopsection
-
-\startsection[title={a few details}]
-
-In \CONTEXT\ setups are a rather common variant on macros (\TEX\ commands) but
-with their own namespace. An example of a setup is:
-
-\starttyping
-\startsetup doc:print
- \setuppapersize[A4][A4]
-\stopsetup
-
-\startsetup doc:screen
- \setuppapersize[S6][S4]
-\stopsetup
-\stoptyping
-
-Given the previous definitions, later on we can say something like:
-
-\starttyping
-\doifmodeelse {paper} {
- \setup[doc:print]
-} {
- \setup[doc:screen]
-}
-\stoptyping
-
-Another example is:
-
-\starttyping
-\startsetup[doc:header]
- \marking[chapter]
- \space
- --
- \space
- \pagenumber
-\stopsetup
-\stoptyping
-
-in combination with:
-
-\starttyping
-\setupheadertexts[\setup{doc:header}]
-\stoptyping
-
-Here the advantage is that instead of ending up with an unreadable header
-definitions, we use a nicely formatted setup. An important property of setups and
-the reason why they were introduced long ago is that spaces and newlines are
-ignored in the definition. This means that we don't have to worry about so called
-spurious spaces but it also means that when we do want a space, we have to use
-the \type {\space} command.
-
-The only difference between setups and \XML\ setups is that the following ones
-get an argument (\type {#1}) that reflects the current node in the \XML\ tree.
-
-\stopsection
-
-\startsection[title={CDATA}]
-
-What to do with \type {CDATA}? There are a few methods at tle \LUA\ end for
-dealing with it but here we just mention how you can influence the rendering.
-There are four macros that play a role here:
-
-\starttyping
-\unexpanded\def\xmlcdataobeyedline {\obeyedline}
-\unexpanded\def\xmlcdataobeyedspace{\strut\obeyedspace}
-\unexpanded\def\xmlcdatabefore {\begingroup\tt}
-\unexpanded\def\xmlcdataafter {\endgroup}
-\stoptyping
-
-Technically you can overload them but beware of side effects. Normally you won't
-see much \type {CDATA} and whenever we do, it involves special data that needs
-very special treatment anyway.
-
-\stopsection
-
-\startsection[title={Entities}]
-
-As usual with any way of encoding documents you need escapes in order to encode
-the characters that are used in tagging the content, embedding comments, escaping
-special characters in strings (in programming languages), etc. In \XML\ this
-means that in order characters like \type {<} you need an escape like \type
-{&lt;} and in order then to encode an \type {&} you need \type {&amp;}.
-
-In a typesetting workflow using a programming language like \TEX, another problem
-shows up. There we have different special characters, like \type {$ $} for triggering
-math, but also the backslash, braces etc. Even one such special character is already
-enough to have yet another escaping mechanism at work.
-
-Ideally a user should not worry about these issues but it helps figuring out issues
-when you know what happens under the hood. Also it is good to know that in the
-code there are several ways to deal with these issues. Take the following document:
-
-\starttyping
-<text>
- Here we have a bit of a &lt;&mess&gt;:
-
- # &#35;
- % &#37;
- \ &#92;
- { &#123;
- | &#124;
- } &#125;
- ~ &#126;
-</text>
-\stoptyping
-
-When the file is read the \type {&lt;} entity will be replaced by \type {<} and
-the \type {&gt;} by \type {>}. The numeric entities will be replaced by the
-characters they refer to. The \type {&mess} is kind of special. We do preload
-a huge list of more or less standardized entities but \type {mess} is not in
-there. However, it is possible to have it defined in the document preamble, like:
-
-\starttyping
-<!DOCTYPE dummy SYSTEM "dummy.dtd" [
- <!ENTITY mess "what a mess" >
-]>
-\stoptyping
-
-or even this:
-
-\starttyping
-<!DOCTYPE dummy SYSTEM "dummy.dtd" [
- <!ENTITY mess "<p>what a mess</p>" >
-]>
-\stoptyping
-
-You can also define it in your document style using one of:
-
-\startxmlcmd {\cmdbasicsetup{xmlsetentity}}
- replaces entity with name \cmdinternal {cd:name} by \cmdinternal {cd:text}
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmltexentity}}
- replaces entity with name \cmdinternal {cd:name} by \cmdinternal {cd:text}
- typeset under a \TEX\ regime
-\stopxmlcmd
-
-Such a definition will always have a higher priority than the one defined
-in the document. Anyway, when the document is read in all entities are
-resolved and those that need a special treatment because they map to some
-text are stored in such a way that we can roundtrip them. As a consequence,
-as soon as the content gets pushed into \TEX, we need not only to intercept
-special characters but also have to make sure that the following works:
-
-\starttyping
-\xmltexentity {tex} {\TEX}
-\stoptyping
-
-Here the backslash starts a control sequence while in regular content a
-backslash is just that: a backslash.
-
-Special characters are really special when we have to move text around
-in a \TEX\ ecosystem.
-
-\starttyping
-<text>
- <title>About #3</title>
-</text>
-\stoptyping
-
-If we map and define title as follows:
-
-\starttyping
-\startxmlsetup xml:title
- \title{\xmlflush{#1}}
-\stopxmlsetup
-\stoptyping
-
-normally something \type {\xmlflush {id::123}} will be written to the
-auxiliary file and in most cases that is quite okay, but if we have this:
-
-\starttyping
-\setuphead[title][expansion=yes]
-\stoptyping
-
-then we don't want the \type {#} to end up as hash because later on \TEX\
-can get very confused about it because it sees some argument then in a
-probably unexpected way. This is solved by escaping the hash like this:
-
-\starttyping
-About \Ux{23}3
-\stoptyping
-
-The \type {\Ux} command will convert its hexadecimal argument into a
-character. Of course one then needs to typeset such a text under a \TEX\
-character regime but that is normally the case anyway.
-
-\stopsection
-
-\stopchapter
-
-\startchapter[title={Commands}]
-
-\startsection[title={nodes and lpaths}]
-
-The amount of commands available for manipulating the \XML\ file is rather large.
-Many of the commands cooperate with the already discussed setups, a fancy name
-for a collection of macro calls either or not mixed with text.
-
-Most of the commands are just shortcuts to \LUA\ calls, which means that the real
-work is done by \LUA. In fact, what happens is that we have a continuous transfer
-of control from \TEX\ to \LUA, where \LUA\ prints back either data (like element
-content or attribute values) or just invokes a setup whereby it passes a
-reference to the node resolved conform the path expression. The invoked setup
-itself might return control to \LUA\ again, etc.
-
-This sounds complicated but examples will show what we mean here. First we
-present the whole repertoire of commands. Because users can read the source code,
-they might uncover more commands, but only the ones discussed here are official.
-The commands are grouped in categories.
-
-In the following sections \cmdinternal {cd:node} means a reference to a node:
-this can be the identifier of the root (the loaded xml tree) or a reference to a
-node in that tree (often the result of some lookup. A \cmdinternal {cd:lpath} is
-a fancy name for a path expression (as with \XSLT) but resolved by \LUA.
-
-\stopsection
-
-\startsection[title={commands}]
-
-There are a lot of commands available but you probably can ignore most of them.
-We try to be complete which means that there is for instance \type {\xmlfirst} as
-well as \type {\xmllast} but you probably never need the last one. There are also
-commands that were used when testing this interface and we see no reason to
-remove them. Some obscure ones are used in modules and after a while even I often
-forget that they exist. To give you an idea of what commands are important we
-show their use in generating the \CONTEXT\ command definitions (\type
-{x-set-11.mkiv}) per January 2016:
-
-\startcolumns[n=2,balance=yes]
-\starttabulate[|l|r|]
-\NC \type {\xmlall} \NC 1 \NC \NR
-\NC \type {\xmlatt} \NC 23 \NC \NR
-\NC \type {\xmlattribute} \NC 1 \NC \NR
-\NC \type {\xmlcount} \NC 1 \NC \NR
-\NC \type {\xmldoif} \NC 2 \NC \NR
-\NC \type {\xmldoifelse} \NC 1 \NC \NR
-\NC \type {\xmlfilterlist} \NC 4 \NC \NR
-\NC \type {\xmlflush} \NC 5 \NC \NR
-\NC \type {\xmlinclude} \NC 1 \NC \NR
-\NC \type {\xmlloadonly} \NC 1 \NC \NR
-\NC \type {\xmlregisterdocumentsetup} \NC 1 \NC \NR
-\NC \type {\xmlsetsetup} \NC 1 \NC \NR
-\NC \type {\xmlsetup} \NC 4 \NC \NR
-\stoptabulate
-\stopcolumns
-
-As you can see filtering, flushing and accessing attributes score high. Below we show
-the statistics of a quite complex rendering (5 variants of schoolbooks: basic book,
-answers, teachers guide, worksheets, full blown version with extensive tracing).
-
-\startcolumns[n=2,balance=yes]
-\starttabulate[|l|r|]
-\NC \type {\xmladdindex} \NC 3 \NC \NR
-\NC \type {\xmlall} \NC 5 \NC \NR
-\NC \type {\xmlappendsetup} \NC 1 \NC \NR
-\NC \type {\xmlapplyselectors} \NC 1 \NC \NR
-\NC \type {\xmlatt} \NC 40 \NC \NR
-\NC \type {\xmlattdef} \NC 9 \NC \NR
-\NC \type {\xmlattribute} \NC 10 \NC \NR
-\NC \type {\xmlbadinclusions} \NC 3 \NC \NR
-\NC \type {\xmlconcat} \NC 3 \NC \NR
-\NC \type {\xmlcount} \NC 1 \NC \NR
-\NC \type {\xmldelete} \NC 11 \NC \NR
-\NC \type {\xmldoif} \NC 39 \NC \NR
-\NC \type {\xmldoifelse} \NC 28 \NC \NR
-\NC \type {\xmldoifelsetext} \NC 13 \NC \NR
-\NC \type {\xmldoifnot} \NC 2 \NC \NR
-\NC \type {\xmldoifnotselfempty} \NC 1 \NC \NR
-\NC \type {\xmlfilter} \NC 100 \NC \NR
-\NC \type {\xmlfirst} \NC 51 \NC \NR
-\NC \type {\xmlflush} \NC 69 \NC \NR
-\NC \type {\xmlflushcontext} \NC 2 \NC \NR
-\NC \type {\xmlinclude} \NC 1 \NC \NR
-\NC \type {\xmlincludeoptions} \NC 5 \NC \NR
-\NC \type {\xmlinclusion} \NC 16 \NC \NR
-\NC \type {\xmlinjector} \NC 1 \NC \NR
-\NC \type {\xmlloaddirectives} \NC 1 \NC \NR
-\NC \type {\xmlmapvalue} \NC 4 \NC \NR
-\NC \type {\xmlmatch} \NC 1 \NC \NR
-\NC \type {\xmlprependsetup} \NC 5 \NC \NR
-\NC \type {\xmlregisterdocumentsetup} \NC 2 \NC \NR
-\NC \type {\xmlregistersetup} \NC 1 \NC \NR
-\NC \type {\xmlremapnamespace} \NC 1 \NC \NR
-\NC \type {\xmlsetfunction} \NC 2 \NC \NR
-\NC \type {\xmlsetinjectors} \NC 2 \NC \NR
-\NC \type {\xmlsetsetup} \NC 11 \NC \NR
-\NC \type {\xmlsetup} \NC 76 \NC \NR
-\NC \type {\xmlstrip} \NC 1 \NC \NR
-\NC \type {\xmlstripanywhere} \NC 1 \NC \NR
-\NC \type {\xmltag} \NC 1 \NC \NR
-\NC \type {\xmltext} \NC 53 \NC \NR
-\NC \type {\xmlvalue} \NC 2 \NC \NR
-\stoptabulate
-\stopcolumns
-
-Here many more are used but this is an exceptional case. The top is again
-dominated by filtering, flushing and attribute consulting. The list can actually
-be smaller. For instance, the \type {\xmlcount} can just as well be \type
-{\xmlfilter} with a \type {count} finalizer. There are also some special ones,
-like the injectors, that are needed for finetuning the final result.
-
-\stopsection
-
-\startsection[title={loading}]
-
-\startxmlcmd {\cmdbasicsetup{xmlloadfile}}
- loads the file \cmdinternal {cd:file} and registers it under \cmdinternal
- {cd:name} and applies either given or standard \cmdinternal
- {cd:xmlsetup} (alias: \type {\xmlload})
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlloadbuffer}}
- loads the buffer \cmdinternal {cd:buffer} and registers it under
- \cmdinternal {cd:name} and applies either given or standard
- \cmdinternal {cd:xmlsetup}
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlloaddata}}
- loads \cmdinternal {cd:text} and registers it under \cmdinternal
- {cd:name} and applies either given or standard \cmdinternal
- {cd:xmlsetup}
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlloadonly}}
- loads \cmdinternal {cd:text} and registers it under \cmdinternal
- {cd:name} and applies either given or standard \cmdinternal
- {cd:xmlsetup} but doesn't flush the content
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlinclude}}
- includes the file specified by attribute \cmdinternal {cd:name} of the
- element located by \cmdinternal {cd:lpath} at node \cmdinternal {cd:node}
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlprocessfile}}
- registers file \cmdinternal {cd:file} as \cmdinternal {cd:name} and
- process the tree starting with \cmdinternal {cd:xmlsetup} (alias:
- \type {\xmlprocess})
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlprocessbuffer}}
- registers buffer \cmdinternal {cd:name} as \cmdinternal {cd:name} and process
- the tree starting with \cmdinternal {cd:xmlsetup}
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlprocessdata}}
- registers \cmdinternal {cd:text} as \cmdinternal {cd:name} and process
- the tree starting with \cmdinternal {cd:xmlsetup}
-\stopxmlcmd
-
-The initial setup defaults to \type {xml:process} that is defined
-as follows:
-
-\starttyping
-\startsetups xml:process
- \xmlregistereddocumentsetups\xmldocument
- \xmlmain\xmldocument
-\stopsetups
-\stoptyping
-
-First we apply the setups associated with the document (including common setups)
-and then we flush the whole document. The macro \type {\xmldocument} expands to
-the current document id. There is also \type {\xmlself} which expands to the
-current node number (\type {#1} in setups).
-
-\startxmlcmd {\cmdbasicsetup{xmlmain}}
- returns the whole document
-\stopxmlcmd
-
-Normally such a flush will trigger a chain reaction of setups associated with the
-child elements.
-
-\stopsection
-
-\startsection[title={saving}]
-
-\startxmlcmd {\cmdbasicsetup{xmlsave}}
- saves the given node \cmdinternal {cd:node} in the file \cmdinternal {cd:file}
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmltofile}}
- saves the match of \cmdinternal {cd:lpath} in the file \cmdinternal {cd:file}
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmltobuffer}}
- saves the match of \cmdinternal {cd:lpath} in the buffer \cmdinternal {cd:buffer}
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmltobufferverbose}}
- saves the match of \cmdinternal {cd:lpath} verbatim in the buffer \cmdinternal
- {cd:buffer}
-\stopxmlcmd
-
-% \startxmlcmd {\cmdbasicsetup{xmltoparameters}}
-% converts the match of \cmdinternal {cd:lpath} to key|/|values (for tracing)
-% \stopxmlcmd
-
-The next command is only needed when you have messed with the tree using
-\LUA\ code.
-
-\startxmlcmd {\cmdbasicsetup{xmladdindex}}
- (re)indexes a tree
-\stopxmlcmd
-
-The following macros are only used in special situations and are not really meant
-for users.
-
-\startxmlcmd {\cmdbasicsetup{xmlraw}}
- flush the content if \cmdinternal {cd:node} with original entities
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{startxmlraw}}
- flush the wrapped content with original entities
-\stopxmlcmd
-
-\stopsection
-
-\startsection[title={flushing data}]
-
-When we flush an element, the associated \XML\ setups are expanded. The most
-straightforward way to flush an element is the following. Keep in mind that the
-returned values itself can trigger setups and therefore flushes.
-
-\startxmlcmd {\cmdbasicsetup{xmlflush}}
- returns all nodes under \cmdinternal {cd:node}
-\stopxmlcmd
-
-You can restrict flushing by using commands that accept a specification.
-
-\startxmlcmd {\cmdbasicsetup{xmltext}}
- returns the text of the matching \cmdinternal {cd:lpath} under \cmdinternal
- {cd:node}
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlpure}}
- returns the text of the matching \cmdinternal {cd:lpath} under \cmdinternal
- {cd:node} without \type {\Ux} escaped special \TEX\ characters
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlflushtext}}
- returns the text of the \cmdinternal {cd:node}
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlflushpure}}
- returns the text of the \cmdinternal {cd:node} without \type {\Ux} escaped
- special \TEX\ characters
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlnonspace}}
- returns the text of the matching \cmdinternal {cd:lpath} under \cmdinternal
- {cd:node} without embedded spaces
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlall}}
- returns all nodes under \cmdinternal {cd:node} that matches \cmdinternal
- {cd:lpath}
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmllastmatch}}
- returns all nodes found in the last match
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlfirst}}
- returns the first node under \cmdinternal {cd:node} that matches \cmdinternal
- {cd:lpath}
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmllast}}
- returns the last node under \cmdinternal {cd:node} that matches \cmdinternal
- {cd:lpath}
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlfilter}}
- at a match of \cmdinternal {cd:lpath} a given filter \type {filter} is applied
- and the result is returned
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlsnippet}}
- returns the \cmdinternal {cd:number}\high{th} element under \cmdinternal
- {cd:node}
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlposition}}
- returns the \cmdinternal {cd:number}\high{th} match of \cmdinternal
- {cd:lpath} at node \cmdinternal {cd:node}; a negative number starts at the
- end (alias: \type {\xmlindex})
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlelement}}
- returns the \cmdinternal {cd:number}\high{th} child of node \cmdinternal {cd:node};
- a negative number starts at the end
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlpos}}
- returns the index (position) in the parent node of \cmdinternal {cd:node}
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlconcat}}
- returns the sequence of nodes that match \cmdinternal {cd:lpath} at
- \cmdinternal {cd:node} whereby \cmdinternal {cd:text} is put between each
- match
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlconcatrange}}
- returns the \cmdinternal {cd:first}\high {th} upto \cmdinternal
- {cd:last}\high {th} of nodes that match \cmdinternal {cd:lpath} at
- \cmdinternal {cd:node} whereby \cmdinternal {cd:text} is put between each
- match
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlcommand}}
- apply the given \cmdinternal {cd:xmlsetup} to each match of \cmdinternal
- {cd:lpath} at node \cmdinternal {cd:node}
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlstrip}}
- remove leading and trailing spaces from nodes under \cmdinternal {cd:node}
- that match \cmdinternal {cd:lpath}
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlstripped}}
- remove leading and trailing spaces from nodes under \cmdinternal {cd:node}
- that match \cmdinternal {cd:lpath} and return the content afterwards
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlstripnolines}}
- remove leading and trailing spaces as well as collapse embedded spaces
- from nodes under \cmdinternal {cd:node} that match \cmdinternal {cd:lpath}
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlstrippednolines}}
- remove leading and trailing spaces as well as collapse embedded spaces from
- nodes under \cmdinternal {cd:node} that match \cmdinternal {cd:lpath} and
- return the content afterwards
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlverbatim}}
- flushes the content verbatim code (without any wrapping, i.e. no fonts
- are selected and such)
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlinlineverbatim}}
- return the content of the node as inline verbatim code; no further
- interpretation (expansion) takes place and spaces are honoured; it uses the
- following wrapper
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{startxmlinlineverbatim}}
- wraps inline verbatim mode using the environment specified (a prefix \type
- {xml:} is added to the environment name)
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmldisplayverbatim}}
- return the content of the node as display verbatim code; no further
- interpretation (expansion) takes place and leading and trailing spaces and
- newlines are treated special; it uses the following wrapper
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{startxmldisplayverbatim}}
- wraps the content in display verbatim using the environment specified (a prefix
- \type {xml:} is added to the environment name)
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlprettyprint}}
- pretty print (with colors) the node \cmdinternal {cd:node}; use the \CONTEXT\
- \SCITE\ lexers when available (\type {\usemodule [scite]})
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlflushspacewise}}
- flush node \cmdinternal {cd:node} obeying spaces and newlines
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlflushlinewise}}
- flush node \cmdinternal {cd:node} obeying newlines
-\stopxmlcmd
-
-\stopsection
-
-\startsection[title={information}]
-
-The following commands return strings. Normally these are used in tests.
-
-\startxmlcmd {\cmdbasicsetup{xmlname}}
- returns the complete name (including namespace prefix) of the
- given \cmdinternal {cd:node}
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlnamespace}}
- returns the namespace of the given \cmdinternal {cd:node}
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmltag}}
- returns the tag of the element, without namespace prefix
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlcount}}
- returns the number of matches of \cmdinternal {cd:lpath} at node \cmdinternal
- {cd:node}
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlatt}}
- returns the value of attribute \cmdinternal {cd:name} or empty if no such
- attribute exists
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlattdef}}
- returns the value of attribute \cmdinternal {cd:name} or \cmdinternal
- {cd:string} if no such attribute exists
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlrefatt}}
- returns the value of attribute \cmdinternal {cd:name} or empty if no such
- attribute exists; a leading \type {#} is removed (nicer for tex)
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlchainatt}}
- returns the value of attribute \cmdinternal {cd:name} or empty if no such
- attribute exists; backtracks till a match is found
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlchainattdef}}
- returns the value of attribute \cmdinternal {cd:name} or \cmdinternal
- {cd:string} if no such attribute exists; backtracks till a match is found
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlattribute}}
- finds a first match for \cmdinternal {cd:lpath} at \cmdinternal {cd:node} and
- returns the value of attribute \cmdinternal {cd:name} or empty if no such
- attribute exists
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlattributedef}}
- finds a first match for \cmdinternal {cd:lpath} at \cmdinternal {cd:node} and
- returns the value of attribute \cmdinternal {cd:name} or \cmdinternal
- {cd:text} if no such attribute exists
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmllastatt}}
- returns the last attribute found (this avoids a lookup)
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlsetatt}}
- set the value of attribute \cmdinternal {cd:name}
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlsetattribute}}
- set the value of attribute \cmdinternal {cd:name} for each match of \cmdinternal
- {cd:lpath}
-\stopxmlcmd
-
-\stopsection
-
-\startsection[title={manipulation}]
-
-You can use \LUA\ code to manipulate the tree and it makes no sense to duplicate
-this in \TEX. In the future we might provide an interface to some of this
-functionality. Keep in mind that manipuating the tree might have side effects as
-we maintain several indices into the tree that also needs to be updated then.
-
-\stopsection
-
-\startsection[title={integration}]
-
-If you write a module that deals with \XML, for instance processing cals tables,
-then you need ways to control specific behaviour. For instance, you might want to
-add a background to the table. Such directives are collected in \XML\ files and
-can be loaded on demand.
-
-\startxmlcmd {\cmdbasicsetup{xmlloaddirectives}}
- loads \CONTEXT\ directives from \cmdinternal {cd:file} that will get
- interpreted when processing documents
-\stopxmlcmd
-
-A directives definition file looks as follows:
-
-\starttyping
-<?xml version="1.0" standalone="yes"?>
-
-<directives>
- <directive attribute='id' value="100"
- setup="cdx:100"/>
- <directive attribute='id' value="101"
- setup="cdx:101"/>
- <directive attribute='cdx' value="colors" element="cals:table"
- setup="cdx:cals:table:colors"/>
- <directive attribute='cdx' value="vertical" element="cals:table"
- setup="cdx:cals:table:vertical"/>
- <directive attribute='cdx' value="noframe" element="cals:table"
- setup="cdx:cals:table:noframe"/>
- <directive attribute='cdx' value="*" element="cals:table"
- setup="cdx:cals:table:*"/>
-</directives>
-\stoptyping
-
-Examples of usage can be found in \type {x-cals.mkiv}. The directive is triggered
-by an attribute. Instead of a setup you can specify a setup to be applied before
-and after the node gets flushed.
-
-\startxmlcmd {\cmdbasicsetup{xmldirectives}}
- apply the setups directive associated with the node
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmldirectivesbefore}}
- apply the before directives associated with the node
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmldirectivesafter}}
- apply the after directives associated with the node
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlinstalldirective}}
- defines a directive that hooks into a handler
-\stopxmlcmd
-
-Normally a directive will be put in the \XML\ file, for instance as:
-
-\starttyping
-<?context-mathml-directive minus reduction yes ?>
-\stoptyping
-
-Here the \type {mathml} is the general class of directives and \type {minus} a
-subclass, in our case a specific element.
-
-\stopsection
-
-\startsection[title={setups}]
-
-The basic building blocks of \XML\ processing are setups. These are just
-collections of macros that are expanded. These setups get one argument passed
-(\type {#1}):
-
-\starttyping
-\startxmlsetups somedoc:somesetup
- \xmlflush{#1}
-\stopxmlsetups
-\stoptyping
-
-This argument is normally a number that internally refers to a specific node in
-the \XML\ tree. The user should see it as an abstract reference and not depend on
-its numeric property. Just think of it as \quote {the current node}. You can (and
-probably will) call such setups using:
-
-\startxmlcmd {\cmdbasicsetup{xmlsetup}}
- expands setup \cmdinternal {cd:setup} and pass \cmdinternal {cd:node} as
- argument
-\stopxmlcmd
-
-However, in most cases the setups are associated to specific elements,
-something that users of \XSLT\ might recognize as templates.
-
-\startxmlcmd {\cmdbasicsetup{xmlsetfunction}}
- associates function \cmdinternal {cd:luafunction} to the elements in
- namespace \cmdinternal {cd:name} that match \cmdinternal {cd:lpath}
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlsetsetup}}
- associates setups \cmdinternal {cd:setup} (\TEX\ code) with the matching
- nodes of \cmdinternal {cd:lpath} or root \cmdinternal {cd:node}
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlprependsetup}}
- pushes \cmdinternal {cd:setup} to the front of global list of setups
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlappendsetup}}
- adds \cmdinternal {cd:setup} to the global list of setups to be applied
- (alias: \type{\xmlregistersetup})
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlbeforesetup}}
- pushes \cmdinternal {cd:setup} into the global list of setups; the
- last setup is the position
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlaftersetup}}
- adds \cmdinternal {cd:setup} to the global list of setups; the last setup
- is the position
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlremovesetup}}
- removes \cmdinternal {cd:setup} from the global list of setups
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlprependdocumentsetup}}
- pushes \cmdinternal {cd:setup} to the front of list of setups to be applied
- to \cmdinternal {cd:name}
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlappenddocumentsetup}}
- adds \cmdinternal {cd:setup} to the list of setups to be applied to
- \cmdinternal {cd:name} (you can also use the alias: \type
- {\xmlregisterdocumentsetup})
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlbeforedocumentsetup}}
- pushes \cmdinternal {cd:setup} into the setups to be applied to \cmdinternal
- {cd:name}; the last setup is the position
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlafterdocumentsetup}}
- adds \cmdinternal {cd:setup} to the setups to be applied to \cmdinternal
- {cd:name}; the last setup is the position
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlremovedocumentsetup}}
- removes \cmdinternal {cd:setup} from the global list of setups to be applied
- to \cmdinternal {cd:name}
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlresetsetups}}
- removes all global setups
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlresetdocumentsetups}}
- removes all setups from the \cmdinternal {cd:name} specific list of setups to
- be applied
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlflushdocumentsetups}{setup}}
- applies \cmdinternal {cd:setup} (can be a list) to \cmdinternal {cd:name}
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlregisteredsetups}}
- applies all global setups to the current document
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlregistereddocumentsetups}}
- applies all document specific \cmdinternal {cd:setup} to document
- \cmdinternal {cd:name}
-\stopxmlcmd
-
-\stopsection
-
-\startsection[title={testing}]
-
-The following test macros all take a \cmdinternal {cd:node} as first argument
-and an \cmdinternal {cd:lpath} as second:
-
-\startxmlcmd {\cmdbasicsetup{xmldoif}}
- expands to \cmdinternal {cd:true} when \cmdinternal {cd:lpath} matches at
- node \cmdinternal {cd:node}
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmldoifnot}}
- expands to \cmdinternal {cd:true} when \cmdinternal {cd:lpath} does not match
- at node \cmdinternal {cd:node}
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmldoifelse}}
- expands to \cmdinternal {cd:true} when \cmdinternal {cd:lpath} matches at
- node \cmdinternal {cd:node} and to \cmdinternal {cd:false} otherwise
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmldoiftext}}
- expands to \cmdinternal {cd:true} when the node matching \cmdinternal
- {cd:lpath} at node \cmdinternal {cd:node} has some content
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmldoifnottext}}
- expands to \cmdinternal {cd:true} when the node matching \cmdinternal
- {cd:lpath} at node \cmdinternal {cd:node} has no content
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmldoifelsetext}}
- expands to \cmdinternal {cd:true} when the node matching \cmdinternal
- {cd:lpath} at node \cmdinternal {cd:node} has content and to \cmdinternal
- {cd:false} otherwise
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmldoifatt}}
- expands to \cmdinternal {cd:true} when the attribute matching \cmdinternal
- {cd:node} and the name given as second argument matches the third argument
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmldoifnotatt}}
- expands to \cmdinternal {cd:true} when the attribute matching \cmdinternal
- {cd:node} and the name given as second argument differs from the third
- argument
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmldoifelseatt}}
- expands to \cmdinternal {cd:true} when the attribute matching \cmdinternal
- {cd:node} and the name given as second argument matches the third argument
- and to \cmdinternal {cd:false} otherwise
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmldoifelseempty}}
- expands to \cmdinternal {cd:true} when the node matching \cmdinternal
- {cd:lpath} at node \cmdinternal {cd:node} is empty and to \cmdinternal
- {cd:false} otherwise
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmldoifelseselfempty}}
- expands to \cmdinternal {cd:true} when the node is empty and to \cmdinternal
- {cd:false} otherwise
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmldoifselfempty}}
- expands to \cmdinternal {cd:true} when \cmdinternal {cd:node} is empty
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmldoifnotselfempty}}
- expands to \cmdinternal {cd:true} when \cmdinternal {cd:node} is not empty
-\stopxmlcmd
-
-\stopsection
-
-\startsection[title={initialization}]
-
-The general setup command (not to be confused with setups) that deals with the
-\MKIV\ tree handler is \type {\setupxml}. There are currently only a few options.
-
-\cmdfullsetup{setupxml}
-
-When you set \type {default} to \cmdinternal {cd:text} elements with no setup
-assigned will end up as text. When set to \type {hidden} such elements will be
-hidden. You can apply the default yourself using:
-
-\startxmlcmd {\cmdbasicsetup{xmldefaulttotext}}
- presets the tree with root \cmdinternal {cd:node} to the handlers set up with
- \type {\setupxml} option \cmdinternal{default}
-\stopxmlcmd
-
-You can set \type {compress} to \type {yes} in which case comment is stripped
-from the tree when the file is read.
-
-\startxmlcmd {\cmdbasicsetup{xmlregisterns}}
- associates an internal namespace (like \type {mml}) with one given in the
- document as \URL\ (like mathml)
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlremapname}}
- changes the namespace and tag of the matching elements
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlremapnamespace}}
- replaces all references to the given namespace to a new one (applied
- recursively)
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlchecknamespace}}
- sets the namespace of the matching elements unless a namespace is already set
-\stopxmlcmd
-
-\stopsection
-
-\startsection[title={helpers}]
-
-Often an attribute will determine the rendering and this may result in many
-tests. Especially when we have multiple attributes that control the output such
-tests can become rather extensive and redundant because one gets $n\times m$ or
-more such tests.
-
-Therefore we have a convenient way to map attributes onto for instance strings or
-commands.
-
-\startxmlcmd {\cmdbasicsetup{xmlmapvalue}}
- associate a \cmdinternal {cd:text} with a \cmdinternal {cd:category} and
- \cmdinternal {cd:name} (alias: \type{\xmlmapval})
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlvalue}}
- expand the value associated with a \cmdinternal {cd:category} and
- \cmdinternal {cd:name} and if not resolved, expand to the \cmdinternal
- {cd:text} (alias: \type{\xmlval})
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmldoifelsevalue}}
- associate a \cmdinternal {cd:text} with a \cmdinternal {cd:category} and
- \cmdinternal {cd:name}
-\stopxmlcmd
-
-This is used as follows. We define a couple of mappings in the same category:
-
-\starttyping
-\xmlmapvalue{emph}{bold} {\bf}
-\xmlmapvalue{emph}{italic}{\it}
-\stoptyping
-
-Assuming that we have associated the following setup with the \type {emph}
-element, we can say (with \type {#1} being the current element):
-
-\starttyping
-\startxmlsetups demo:emph
- \begingroup
- \xmlvalue{emph}{\xmlatt{#1}{type}}{}
- \endgroup
-\stopxmlsetups
-\stoptyping
-
-In this case we have no default. The \type {type} attribute triggers the actions,
-as in:
-
-\starttyping
-normal <emph type='bold'>bold</emph> normal
-\stoptyping
-
-This mechanism is not really bound to elements and attributes so you can use this
-mechanism for other purposes as well.
-
-\stopsection
-
-\startsection[title={Parameters}]
-
-\startbuffer[test]
-<something whatever="alpha">
- <what>
- beta
- </what>
-</something>
-\stopbuffer
-
-\startbuffer
-\startxmlsetups xml:mysetups
- \xmlsetsetup{\xmldocument}{*}{xml:*}
-\stopxmlsetups
-
-\xmlregistersetup{xml:mysetups}
-
-\startxmlsetups xml:something
- parameter : \xmlpar {#1}{whatever}\par
- attribute : \xmlatt {#1}{whatever}\par
- text : \xmlfirst {#1}{what} \par
- \xmlsetpar{#1}{whatever}{gamma}
- parameter : \xmlpar {#1}{whatever}\par
- \xmlflush{#1}
-\stopxmlsetups
-
-\startxmlsetups xml:what
- what: \xmlflush{#1}\par
- parameter : \xmlparam{#1}{..}{whatever}\par
-\stopxmlsetups
-
-\xmlprocessbuffer{main}{test}{}
-\stopbuffer
-
-Say that we have this \XML\ blob:
-
-\typebuffer[test]
-
-With:
-
-\typebuffer
-
-we get:
-
-\getbuffer
-
-Parameters are stored with a node.
-
-\startxmlcmd {\cmdbasicsetup{xmlpar}}
- returns the value of parameter \cmdinternal {cd:name} or empty if no such
- parameter exists
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlparam}}
- finds a first match for \cmdinternal {cd:lpath} at \cmdinternal {cd:node} and
- returns the value of parameter \cmdinternal {cd:name} or empty if no such
- parameter exists
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmllastpar}}
- returns the last parameter found (this avoids a lookup)
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlsetpar}}
- set the value of parameter \cmdinternal {cd:name}
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlsetparam}}
- set the value of parameter \cmdinternal {cd:name} for each match of \cmdinternal
- {cd:lpath}
-\stopxmlcmd
-
-\stopsection
-
-\stopchapter
-
-\startchapter[title={Expressions and filters}]
-
-\startsection[title={path expressions}]
-
-In the previous chapters we used \cmdinternal {cd:lpath} expressions, which are a variant
-on \type {xpath} expressions as in \XSLT\ but in this case more geared towards
-usage in \TEX. This mechanisms will be extended when demands are there.
-
-A path is a sequence of matches. A simple path expression is:
-
-\starttyping
-a/b/c/d
-\stoptyping
-
-Here each \type {/} goes one level deeper. We can go backwards in a lookup with
-\type {..}:
-
-\starttyping
-a/b/../d
-\stoptyping
-
-We can also combine lookups, as in:
-
-\starttyping
-a/(b|c)/d
-\stoptyping
-
-A negated lookup is preceded by a \type {!}:
-
-\starttyping
-a/(b|c)/!d
-\stoptyping
-
-A wildcard is specified with a \type {*}:
-
-\starttyping
-a/(b|c)/!d/e/*/f
-\stoptyping
-
-In addition to these tag based lookups we can use attributes:
-
-\starttyping
-a/(b|c)/!d/e/*/f[@type=whatever]
-\stoptyping
-
-An \type {@} as first character means that we are dealing with an attribute.
-Within the square brackets there can be boolean expressions:
-
-\starttyping
-a/(b|c)/!d/e/*/f[@type=whatever and @id>100]
-\stoptyping
-
-You can use functions as in:
-
-\starttyping
-a/(b|c)/!d/e/*/f[something(text()) == "oeps"]
-\stoptyping
-
-There are a couple of predefined functions:
-
-\starttabulate[|l|l|p|]
-\NC \type{rootposition} \type{order} \NC number \NC the index of the matched root element (kind of special) \NC \NR
-\NC \type{position} \NC number \NC the current index of the matched element in the match list \NC \NR
-\NC \type{match} \NC number \NC the current index of the matched element sub list with the same parent \NC \NR
-\NC \type{first} \NC number \NC \NC \NR
-\NC \type{last} \NC number \NC \NC \NR
-\NC \type{index} \NC number \NC the current index of the matched element in its parent list \NC \NR
-\NC \type{firstindex} \NC number \NC \NC \NR
-\NC \type{lastindex} \NC number \NC \NC \NR
-\NC \type{element} \NC number \NC the element's index \NC \NR
-\NC \type{firstelement} \NC number \NC \NC \NR
-\NC \type{lastelement} \NC number \NC \NC \NR
-\NC \type{text} \NC string \NC the textual representation of the matched element \NC \NR
-\NC \type{content} \NC table \NC the node of the matched element \NC \NR
-\NC \type{name} \NC string \NC the full name of the matched element: namespace and tag \NC \NR
-\NC \type{namespace} \type{ns} \NC string \NC the namespace of the matched element \NC \NR
-\NC \type{tag} \NC string \NC the tag of the matched element \NC \NR
-\NC \type{attribute} \NC string \NC the value of the attribute with the given name of the matched element \NC \NR
-\stoptabulate
-
-There are fundamental differences between \type {position}, \type {match} and
-\type {index}. Each step results in a new list of matches. The \type {position}
-is the index in this new (possibly intermediate) list. The \type {match} is also
-an index in this list but related to the specific match of element names. The
-\type {index} refers to the location in the parent element.
-
-Say that we have:
-
-\starttyping
-<collection>
- <resources>
- <manual>
- <screen>.1.</screen>
- <paper>.1.</paper>
- </manual>
- <manual>
- <paper>.2.</paper>
- <screen>.2.</screen>
- </manual>
- <resources>
- <resources>
- <manual>
- <screen>.3.</screen>
- <paper>.3.</paper>
- </manual>
- <resources>
-<collection>
-\stoptyping
-
-The following then applies:
-
-\starttabulate[|l|l|]
-\NC \type {collection/resources/manual[position()==1]/paper} \NC \type{.1.} \NC \NR
-\NC \type {collection/resources/manual[match()==1]/paper} \NC \type{.1.} \type{.3.} \NC \NR
-\NC \type {collection/resources/manual/paper[index()==1]} \NC \type{.2.} \NC \NR
-\stoptabulate
-
-In most cases the \type {position} test is more restrictive than the \type
-{match} test.
-
-You can pass your own functions too. Such functions are defined in the \type
-{xml.expressions} namespace. We have defined a few shortcuts:
-
-\starttabulate[|l|l|]
-\NC \type {find(str,pattern)} \NC \type{string.find} \NC \NR
-\NC \type {contains(str)} \NC \type{string.find} \NC \NR
-\NC \type {oneof(str,...)} \NC is \type{str} in list \NC \NR
-\NC \type {upper(str)} \NC \type{characters.upper} \NC \NR
-\NC \type {lower(str)} \NC \type{characters.lower} \NC \NR
-\NC \type {number(str)} \NC \type{tonumber} \NC \NR
-\NC \type {boolean(str)} \NC \type{toboolean} \NC \NR
-\NC \type {idstring(str)} \NC removes leading hash \NC \NR
-\NC \type {name(index)} \NC full tag name \NC \NR
-\NC \type {tag(index)} \NC tag name \NC \NR
-\NC \type {namespace(index)} \NC namespace of tag \NC \NR
-\NC \type {text(index)} \NC content \NC \NR
-\NC \type {error(str)} \NC quit and show error \NC \NR
-\NC \type {quit()} \NC quit \NC \NR
-\NC \type {print()} \NC print message \NC \NR
-\NC \type {count(pattern)} \NC number of matches \NC \NR
-\NC \type {child(pattern)} \NC take child that matches \NC \NR
-\stoptabulate
-
-
-You can also use normal \LUA\ functions as long as you make sure that you pass
-the right arguments. There are a few predefined variables available inside such
-functions.
-
-\starttabulate[|Tl|l|p|]
-\NC \type{list} \NC table \NC the list of matches \NC \NR
-\NC \type{l} \NC number \NC the current index in the list of matches \NC \NR
-\NC \type{ll} \NC element \NC the current element that matched \NC \NR
-\NC \type{order} \NC number \NC the position of the root of the path \NC \NR
-\stoptabulate
-
-The given expression between \type {[]} is converted to a \LUA\ expression so you
-can use the usual operators:
-
-\starttyping
-== ~= <= >= < > not and or ()
-\stoptyping
-
-In addition, \type {=} equals \type {==} and \type {!=} is the same as \type
-{~=}. If you mess up the expression, you quite likely get a \LUA\ error message.
-
-\stopsection
-
-\startsection[title={css selectors}]
-
-\startbuffer[selector-001]
-<?xml version="1.0" ?>
-
-<a>
- <b class="one">b.one</b>
- <b class="two">b.two</b>
- <b class="one two">b.one.two</b>
- <b class="three">b.three</b>
- <b id="first">b#first</b>
- <c>c</c>
- <d>d e</d>
- <e>d e</e>
- <e>d e e</e>
- <d>d f</d>
- <f foo="bar">@foo = bar</f>
- <f bar="foo">@bar = foo</f>
- <f bar="foo1">@bar = foo1</f>
- <f bar="foo2">@bar = foo2</f>
- <f bar="foo3">@bar = foo3</f>
- <f bar="foo+4">@bar = foo+4</f>
- <g>g</g>
- <g><gg><d>g gg d</d></gg></g>
- <g><gg><f>g gg f</f></gg></g>
- <g><gg><f class="one">g gg f.one</f></gg></g>
- <g>g</g>
- <g><gg><f class="two">g gg f.two</f></gg></g>
- <g><gg><f class="three">g gg f.three</f></gg></g>
- <g><f class="one">g f.one</f></g>
- <g><f class="three">g f.three</f></g>
- <h whatever="four five six">@whatever = four five six</h>
-</a>
-\stopbuffer
-
-\xmlloadbuffer{selector-001}{selector-001}
-
-\startxmlsetups xml:selector:demo
- \advance\scratchcounter\plusone
- \inleftmargin{\the\scratchcounter}\ignorespaces\xmlverbatim{#1}\par
-\stopxmlsetups
-
-\unexpanded\def\showCSSdemo#1#2%
- {\blank
- \textrule{\tttf#2}
- \startlines
- \dontcomplain
- \tttf \obeyspaces
- \scratchcounter\zerocount
- \xmlcommand{#1}{#2}{xml:selector:demo}
- \stoplines
- \blank}
-
-The \CSS\ approach to filtering is a bit different from the path based one and is
-supported too. In fact, you can combine both methods. Depending on what you
-select, the \CSS\ one can be a little bit faster too. It has the advantage that
-one can select more in one go but at the same time looks a bit less attractive.
-This method was added just to show that it can be done but might be useful too. A
-selector is given between curly braces (after all \CSS\ uses them and they have no
-function yet in the parser.
-
-\starttyping
-\xmlall{#1}{{foo bar .whatever, bar foo .whatever}}
-\stoptyping
-
-The following methods are supported:
-
-\starttabulate[|T||]
-\NC element \NC all tags element \NC \NR
-\NC element-1 > element-2 \NC all tags element-2 with parent tag element-1 \NC \NR
-\NC element-1 + element-2 \NC all tags element-2 preceded by tag element-1 \NC \NR
-\NC element-1 ~ element-2 \NC all tags element-2 preceded by tag element-1 \NC \NR
-\NC element-1 element-2 \NC all tags element-2 inside tag element-1 \NC \NR
-\NC [attribute] \NC has attribute \NC \NR
-\NC [attribute=value] \NC attribute equals value\NC \NR
-\NC [attribute\lettertilde =value] \NC attribute contains value (space is separator) \NC \NR
-\NC [attribute\letterhat ="value"] \NC attribute starts with value \NC \NR
-\NC [attribute\letterdollar="value"] \NC attribute ends with value \NC \NR
-\NC [attribute*="value"] \NC attribute contains value \NC \NR
-\NC .class \NC has class \NC \NR
-\NC \letterhash id \NC has id \NC \NR
-\NC :nth-child(n) \NC the child at index n \NC \NR
-\NC :nth-last-child(n) \NC the child at index n from the end \NC \NR
-\NC :first-child \NC the first child \NC \NR
-\NC :last-child \NC the last child \NC \NR
-\NC :nth-of-type(n) \NC the match at index n \NC \NR
-\NC :nth-last-of-type(n) \NC the match at index n from the end \NC \NR
-\NC :first-of-type \NC the first match \NC \NR
-\NC :last-of-type \NC the last match \NC \NR
-\NC :only-of-type \NC the only match or nothing \NC \NR
-\NC :only-child \NC the only child or nothing \NC \NR
-\NC :empty \NC only when empty \NC \NR
-\NC :root \NC the whole tree \NC \NR
-\stoptabulate
-
-The next pages show some examples. For that we use the demo file:
-
-\typebuffer[selector-001]
-
-The class and id selectors often only make sense in \HTML\ like documents but they
-are supported nevertheless. They are after all just shortcuts for filtering by
-attribute. The class filtering is special in the sense that it checks for a class
-in a list of classes given in an attribute.
-
-\showCSSdemo{selector-001}{{.one}}
-\showCSSdemo{selector-001}{{.one, .two}}
-\showCSSdemo{selector-001}{{.one, .two, \letterhash first}}
-
-Attributes can be filtered by presence, value, partial value and such. Quotes are
-optional but we advice to use them.
-
-\showCSSdemo{selector-001}{{[foo], [bar=foo]}}
-\showCSSdemo{selector-001}{{[bar\lettertilde=foo]}}
-\showCSSdemo{selector-001}{{[bar\letterhat="foo"]}}
-\showCSSdemo{selector-001}{{[whatever\lettertilde="five"]}}
-
-You can of course combine the methods as in:
-
-\showCSSdemo{selector-001}{{g f .one, g f .three}}
-\showCSSdemo{selector-001}{{g > f .one, g > f .three}}
-\showCSSdemo{selector-001}{{d + e}}
-\showCSSdemo{selector-001}{{d ~ e}}
-\showCSSdemo{selector-001}{{d ~ e, g f .one, g f .three}}
-
-You can also negate the result by using \type {:not} on a simple expression:
-
-\showCSSdemo{selector-001}{{:not([whatever\lettertilde="five"])}}
-\showCSSdemo{selector-001}{{:not(d)}}
-
-The child and match selectors are also supported:
-
-\showCSSdemo{selector-001}{{a:nth-child(3)}}
-\showCSSdemo{selector-001}{{a:nth-last-child(3)}}
-\showCSSdemo{selector-001}{{g:nth-of-type(3)}}
-\showCSSdemo{selector-001}{{g:nth-last-of-type(3)}}
-\showCSSdemo{selector-001}{{a:first-child}}
-\showCSSdemo{selector-001}{{a:last-child}}
-\showCSSdemo{selector-001}{{e:first-of-type}}
-\showCSSdemo{selector-001}{{gg d:only-of-type}}
-
-Instead of numbers you can also give the \type {an} and \type {an+b} formulas
-as well as the \type {odd} and \type {even} keywords:
-
-\showCSSdemo{selector-001}{{a:nth-child(even)}}
-\showCSSdemo{selector-001}{{a:nth-child(odd)}}
-\showCSSdemo{selector-001}{{a:nth-child(3n+1)}}
-\showCSSdemo{selector-001}{{a:nth-child(2n+3)}}
-
-There are a few special cases:
-
-\showCSSdemo{selector-001}{{g:empty}}
-\showCSSdemo{selector-001}{{g:root}}
-\showCSSdemo{selector-001}{{*}}
-
-Combining the \CSS\ methods with the regular ones is possible:
-
-\showCSSdemo{selector-001}{{g gg f .one}}
-\showCSSdemo{selector-001}{g/gg/f[@class='one']}
-\showCSSdemo{selector-001}{g/{gg f .one}}
-
-\startbuffer[selector-002]
-<?xml version="1.0" ?>
-
-<document>
- <title class="one" >title 1</title>
- <title class="two" >title 2</title>
- <title class="one" >title 3</title>
- <title class="three">title 4</title>
-</document>
-\stopbuffer
-
-The next examples we use this file:
-
-\typebuffer[selector-002]
-
-\xmlloadbuffer{selector-002}{selector-002}
-
-When we filter from this (not too well structured) tree we can use both
-methods to achieve the same:
-
-\showCSSdemo{selector-002}{{document title .one, document title .three}}
-
-\showCSSdemo{selector-002}{/document/title[(@class='one') or (@class='three')]}
-
-However, imagine this file:
-
-\startbuffer[selector-003]
-<?xml version="1.0" ?>
-
-<document>
- <title class="one">title 1</title>
- <subtitle class="sub">title 1.1</subtitle>
- <title class="two">title 2</title>
- <subtitle class="sub">title 2.1</subtitle>
- <title class="one">title 3</title>
- <subtitle class="sub">title 3.1</subtitle>
- <title class="two">title 4</title>
- <subtitle class="sub">title 4.1</subtitle>
-</document>
-\stopbuffer
-
-\typebuffer[selector-003]
-
-\xmlloadbuffer{selector-003}{selector-003}
-
-The next filter in easier with the \CSS\ selector methods because these accumulate
-independent (simple) expressions:
-
-\showCSSdemo{selector-003}{{document title .one + subtitle, document title .two + subtitle}}
-
-Watch how we get an output in the document order. Because we render a sequential document
-a combined filter will trigger a sorting pass.
-
-\stopsection
-
-\startsection[title={functions as filters}]
-
-At the \LUA\ end a whole \cmdinternal {cd:lpath} expression results in a (set of) node(s)
-with its environment, but that is hardly usable in \TEX. Think of code like:
-
-\starttyping
-for e in xml.collected(xml.load('text.xml'),"title") do
- -- e = the element that matched
-end
-\stoptyping
-
-The older variant is still supported but you can best use the previous variant.
-
-\starttyping
-for r, d, k in xml.elements(xml.load('text.xml'),"title") do
- -- r = root of the title element
- -- d = data table
- -- k = index in data table
-end
-\stoptyping
-
-Here \type {d[k]} points to the \type {title} element and in this case all titles
-in the tree pass by. In practice this kind of code is encapsulated in function
-calls, like those returning elements one by one, or returning the first or last
-match. The result is then fed back into \TEX, possibly after being altered by an
-associated setup. We've seen the wrappers to such functions already in a previous
-chapter.
-
-In addition to the previously discussed expressions, one can add so called
-filters to the expression, for instance:
-
-\starttyping
-a/(b|c)/!d/e/text()
-\stoptyping
-
-In a filter, the last part of the \cmdinternal {cd:lpath} expression is a
-function call. The previous example returns the text of each element \type {e}
-that results from matching the expression. When running \TEX\ the following
-functions are available. Some are also available when using pure \LUA. In \TEX\
-you can often use one of the macros like \type {\xmlfirst} instead of a \type
-{\xmlfilter} with finalizer \type {first()}. The filter can be somewhat faster
-but that is hardly noticeable.
-
-\starttabulate[|l|l|p|]
-\NC \type {context()} \NC string \NC the serialized text with \TEX\ catcode regime \NC \NR
-%NC \type {ctxtext()} \NC string \NC \NC \NR
-\NC \type {function()} \NC string \NC depends on the function \NC \NR
-%
-\NC \type {name()} \NC string \NC the (remapped) namespace \NC \NR
-\NC \type {tag()} \NC string \NC the name of the element \NC \NR
-\NC \type {tags()} \NC list \NC the names of the element \NC \NR
-%
-\NC \type {text()} \NC string \NC the serialized text \NC \NR
-\NC \type {upper()} \NC string \NC the serialized text uppercased \NC \NR
-\NC \type {lower()} \NC string \NC the serialized text lowercased \NC \NR
-\NC \type {stripped()} \NC string \NC the serialized text stripped \NC \NR
-\NC \type {lettered()} \NC string \NC the serialized text only letters (cf. \UNICODE) \NC \NR
-%
-\NC \type {count()} \NC number \NC the number of matches \NC \NR
-\NC \type {index()} \NC number \NC the matched index in the current path \NC \NR
-\NC \type {match()} \NC number \NC the matched index in the preceding path \NC \NR
-%
-%NC \type {lowerall()} \NC string \NC \NC \NR
-%NC \type {upperall()} \NC string \NC \NC \NR
-%
-\NC \type {attribute(name)} \NC content \NC returns the attribute with the given name \NC \NR
-\NC \type {chainattribute(name)} \NC content \NC sidem, but backtracks till one is found \NC \NR
-\NC \type {command(name)} \NC content \NC expands the setup with the given name for each found element \NC \NR
-\NC \type {position(n)} \NC content \NC processes the \type {n}\high{th} instance of the found element \NC \NR
-\NC \type {all()} \NC content \NC processes all instances of the found element \NC \NR
-%NC \type {default} \NC content \NC all \NC \NR
-\NC \type {reverse()} \NC content \NC idem in reverse order \NC \NR
-\NC \type {first()} \NC content \NC processes the first instance of the found element \NC \NR
-\NC \type {last()} \NC content \NC processes the last instance of the found element \NC \NR
-\NC \type {concat(...)} \NC content \NC concatinates the match \NC \NC \NR
-\NC \type {concatrange(from,to,...)} \NC content \NC concatinates a range of matches \NC \NC \NR
-\stoptabulate
-
-The extra arguments of the concatinators are: \type {separator} (string), \type
-{lastseparator} (string) and \type {textonly} (a boolean).
-
-These filters are in fact \LUA\ functions which means that if needed more of them
-can be added. Indeed this happens in some of the \XML\ related \MKIV\ modules,
-for instance in the \MATHML\ processor.
-
-\stopsection
-
-\startsection[title={example}]
-
-The number of commands is rather large and if you want to avoid them this is
-often possible. Take for instance:
-
-\starttyping
-\xmlall{#1}{/a/b[position()>3]}
-\stoptyping
-
-Alternatively you can use:
-
-\starttyping
-\xmlfilter{#1}{/a/b[position()>3]/all()}
-\stoptyping
-
-and actually this is also faster as internally it avoids a function call. Of
-course in practice this is hardly measurable.
-
-In previous examples we've already seen quite some expressions, and it might be
-good to point out that the syntax is modelled after \XSLT\ but is not quite the
-same. The reason is that we started with a rather minimal system and have already
-styles in use that depend on compatibility.
-
-\starttyping
-namespace:// axis node(set) [expr 1]..[expr n] / ... / filter
-\stoptyping
-
-When we are inside a \CONTEXT\ run, the namespace is \type {tex}. Hoewever, if
-you want not to print back to \TEX\ you need to be more explicit. Say that we
-typeset examns and have a (not that logical) structure like:
-
-\starttyping
-<question>
- <text>...</text>
- <answer>
- <item>one</item>
- <item>two</item>
- <item>three</item>
- </answer>
- <alternative>
- <condition>true</condition>
- <score>1</score>
- </alternative>
- <alternative>
- <condition>false</condition>
- <score>0</score>
- </alternative>
- <alternative>
- <condition>true</condition>
- <score>2</score>
- </alternative>
-</question>
-\stoptyping
-
-Say that we typeset the questions with:
-
-\starttyping
-\startxmlsetups question
- \blank
- score: \xmlfunction{#1}{totalscore}
- \blank
- \xmlfirst{#1}{text}
- \startitemize
- \xmlfilter{#1}{/answer/item/command(answer:item)}
- \stopitemize
- \endgraf
- \blank
-\stopxmlsetups
-\stoptyping
-
-Each item in the answer results in a call to:
-
-\starttyping
-\startxmlsetups answer:item
- \startitem
- \xmlflush{#1}
- \endgraf
- \xmlfilter{#1}{../../alternative[position()=rootposition()]/
- condition/command(answer:condition)}
- \stopitem
-\stopxmlsetups
-\stoptyping
-
-\starttyping
-\startxmlsetups answer:condition
- \endgraf
- condition: \xmlflush{#1}
- \endgraf
-\stopxmlsetups
-\stoptyping
-
-Now, there are two rather special filters here. The first one involves
-calculating the total score. As we look forward we use a function to deal with
-this.
-
-\starttyping
-\startluacode
-function xml.functions.totalscore(root)
- local score = 0
- for e in xml.collected(root,"/alternative") do
- score = score + xml.filter(e,"xml:///score/number()") or 0
- end
- tex.write(score)
-end
-\stopluacode
-\stoptyping
-
-Watch how we use the namespace to keep the results at the \LUA\ end.
-
-The second special trick shown here is to limit a match using the current
-position of the root (\type {#}) match.
-
-As you can see, a path expression can be more than just filtering a few nodes. At
-the end of this manual you will find a bunch of examples.
-
-\stopsection
-
-\startsection[title={tables}]
-
-If you want to know how the internal \XML\ tables look you can print such a
-table:
-
-\starttyping
-print(table.serialize(e))
-\stoptyping
-
-This produces for instance:
-
-% s = xml.convert("<document><demo label='whatever'>some text</demo></document>")
-% print(table.serialize(xml.filter(s,"demo")[1]))
-
-\starttyping
-t={
- ["at"]={
- ["label"]="whatever",
- },
- ["dt"]={ "some text" },
- ["ns"]="",
- ["rn"]="",
- ["tg"]="demo",
-}
-\stoptyping
-
-The \type {rn} entry is the renamed namespace (when renaming is applied). If you
-see tags like \type {@pi@} this means that we don't have an element, but (in this
-case) a processing instruction.
-
-\starttabulate[|l|p|]
-\NC \type {@rt@} \NC the root element \NC \NR
-\NC \type {@dd@} \NC document definition \NC \NR
-\NC \type {@cm@} \NC comment, like \type {<!-- whatever -->} \NC \NR
-\NC \type {@cd@} \NC so called \type {CDATA} \NC \NR
-\NC \type {@pi@} \NC processing instruction, like \type {<?whatever we want ?>} \NC \NR
-\stoptabulate
-
-There are many ways to deal with the content, but in the perspective of \TEX\
-only a few matter.
-
-\starttabulate[|l|p|]
-\NC \type {xml.sprint(e)} \NC print the content to \TEX\ and apply setups if needed \NC \NR
-\NC \type {xml.tprint(e)} \NC print the content to \TEX\ (serialize elements verbose) \NC \NR
-\NC \type {xml.cprint(e)} \NC print the content to \TEX\ (used for special content) \NC \NR
-\stoptabulate
-
-Keep in mind that anything low level that you uncover is not part of the official
-interface unless mentioned in this manual.
-
-\stopsection
-
-\stopchapter
-
-\startchapter[title={Tips and tricks}]
-
-\startsection[title={tracing}]
-
-It can be hard to debug code as much happens kind of behind the screens.
-Therefore we have a couple of tracing options. Of course you can typeset some
-status information, using for instance:
-
-\startxmlcmd {\cmdbasicsetup{xmlshow}}
- typeset the tree given by \cmdinternal {cd:node}
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlinfo}}
- typeset the name in the element given by \cmdinternal {cd:node}
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlpath}}
- returns the complete path (including namespace prefix and index) of the
- given \cmdinternal {cd:node}
-\stopxmlcmd
-
-\startbuffer[demo]
-<?xml version "1.0"?>
-<document>
- <section>
- <content>
- <p>first</p>
- <p><b>second</b></p>
- </content>
- </section>
- <section>
- <content>
- <p><b>third</b></p>
- <p>fourth</p>
- </content>
- </section>
-</document>
-\stopbuffer
-
-Say that we have the following \XML:
-
-\typebuffer[demo]
-
-and the next definitions:
-
-\startbuffer
-\startxmlsetups xml:demo:base
- \xmlsetsetup{#1}{p|b}{xml:demo:*}
-\stopxmlsetups
-
-\startxmlsetups xml:demo:p
- \xmlflush{#1}
- \par
-\stopxmlsetups
-
-\startxmlsetups xml:demo:b
- \par
- \xmlpath{#1} : \xmlflush{#1}
- \par
-\stopxmlsetups
-
-\xmlregisterdocumentsetup{example-10}{xml:demo:base}
-
-\xmlprocessbuffer{example-10}{demo}{}
-\stopbuffer
-
-\typebuffer
-
-This will give us:
-
-\blank \startpacked \getbuffer \stoppacked \blank
-
-If you use \type {\xmlshow} you will get a complete subtree which can
-be handy for tracing but can also lead to large documents.
-
-We also have a bunch of trackers that can be enabled, like:
-
-\starttyping
-\enabletrackers[xml.show,xml.parse]
-\stoptyping
-
-The full list (currently) is:
-
-\starttabulate[|lT|p|]
-\NC xml.entities \NC show what entities are seen and replaced \NC \NR
-\NC xml.path \NC show the result of parsing an lpath expression \NC \NR
-\NC xml.parse \NC show stepwise resolving of expressions \NC \NR
-\NC xml.profile \NC report all parsed lpath expressions (in the log) \NC \NR
-\NC xml.remap \NC show what namespaces are remapped \NC \NR
-\NC lxml.access \NC report errors with respect to resolving (symbolic) nodes \NC \NR
-\NC lxml.comments \NC show the comments that are encountered (if at all) \NC \NR
-\NC lxml.loading \NC show what files are loaded and converted \NC \NR
-\NC lxml.setups \NC show what setups are being associated to elements \NC \NR
-\stoptabulate
-
-In one of our workflows we produce books from \XML\ where the (educational)
-content is organized in many small files. Each book has about 5~chapters and each
-chapter is made of sections that contain text, exercises, resources, etc.\ and so
-the document is assembled from thousands of files (don't worry, runtime inclusion
-is pretty fast). In order to see where in the sources content resides we can
-trace the filename.
-
-\startxmlcmd {\cmdbasicsetup{xmlinclusion}}
- returns the file where the node comes from
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlinclusions}}
- returns the list of files where the node comes from
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlbadinclusions}}
- returns a list of files that were not included due to some problem
-\stopxmlcmd
-
-Of course you have to make sure that these names end up somewhere visible, for
-instance in the margin.
-
-\stopsection
-
-\startsection[title={expansion}]
-
-For novice users the concept of expansion might sound frightening and to some
-extend it is. However, it is important enough to spend some words on it here.
-
-It is good to realize that most setups are sort of immediate. When one setup is
-issued, it can call another one and so on. Normally you won't notice that but
-there are cases where that can be a problem. In \TEX\ you can define a macro,
-take for instance:
-
-\starttyping
-\startxmlsetups xml:foo
- \def\foobar{\xmlfirst{#1}{/bar}}
-\stopxmlsetups
-\stoptyping
-
-you store the reference top node \type {bar} in \type {\foobar} maybe for later use. In
-this case the content is not yet fetched, it will be done when \type {\foobar} is
-called.
-
-\starttyping
-\startxmlsetups xml:foo
- \edef\foobar{\xmlfirst{#1}{/bar}}
-\stopxmlsetups
-\stoptyping
-
-Here the content of \type {bar} becomes the body of the macro. But what if
-\type {bar} itself contains elements that also contain elements. When there
-is a setup for \type {bar} it will be triggered and so on.
-
-When that setup looks like:
-
-\starttyping
-\startxmlsetups xml:bar
- \def\barfoo{\xmlflush{#1}}
-\stopxmlsetups
-\stoptyping
-
-Here we get something like:
-
-\starttyping
-\foobar => {\def\barfoo{...}}
-\stoptyping
-
-When \type {\barfoo} is not defined we get an error and when it is known and expands
-to something weird we might also get an error.
-
-Especially when you don't know what content can show up, this can result in errors
-when an expansion fails, for example because some macro being used is not defined.
-To prevent this we can define a macro:
-
-\starttyping
-\starttexdefinition unexpanded xml:bar:macro #1
- \def\barfoo{\xmlflush{#1}}
-\stoptexdefinition
-
-\startxmlsetups xml:bar
- \texdefinition{xml:bar:macro}{#1}
-\stopxmlsetups
-\stoptyping
-
-The setup \type {xml:bar} will still expand but the replacement text now is just the
-call to the macro, think of:
-
-\starttyping
-\foobar => {\texdefinition{xml:bar:macro}{#1}}
-\stoptyping
-
-But this is often not needed, most \CONTEXT\ commands can handle the expansions
-quite well but it's good to know that there is a way out. So, now to some
-examples. Imagine that we have an \XML\ file that looks as follows:
-
-\starttyping
-<?xml version='1.0' ?>
-<demo>
- <chapter>
- <title>Some <em>short</em> title</title>
- <content>
- zeta
- <index>
- <key>zeta</key>
- <content>zeta again</content>
- </index>
- alpha
- <index>
- <key>alpha</key>
- <content>alpha <em>again</em></content>
- </index>
- gamma
- <index>
- <key>gamma</key>
- <content>gamma</content>
- </index>
- beta
- <index>
- <key>beta</key>
- <content>beta</content>
- </index>
- delta
- <index>
- <key>delta</key>
- <content>delta</content>
- </index>
- done!
- </content>
- </chapter>
-</demo>
-\stoptyping
-
-There are a few structure related elements here: a chapter (with its list entry)
-and some index entries. Both are multipass related and therefore travel around.
-This means that when we let data end up in the auxiliary file, we need to make
-sure that we end up with either expanded data (i.e.\ no references to the \XML\
-tree) or with robust forward and backward references to elements in the tree.
-
-Here we discuss three approaches (and more may show up later): pushing \XML\ into
-the auxiliary file and using references to elements either or not with an
-associated setup. We control the variants with a switch.
-
-\starttyping
-\newcount\TestMode
-
-\TestMode=0 % expansion=xml
-\TestMode=1 % expansion=yes, index, setup
-\TestMode=2 % expansion=yes
-\stoptyping
-
-We apply a couple of setups:
-
-\starttyping
-\startxmlsetups xml:mysetups
- \xmlsetsetup{\xmldocument}{demo|index|content|chapter|title|em}{xml:*}
-\stopxmlsetups
-
-\xmlregistersetup{xml:mysetups}
-\stoptyping
-
-The main document is processed with:
-
-\starttyping
-\startxmlsetups xml:demo
- \xmlflush{#1}
- \subject{contents}
- \placelist[chapter][criterium=all]
- \subject{index}
- \placeregister[index][criterium=all]
- \page % else buffer is forgotten when placing header
-\stopxmlsetups
-\stoptyping
-
-First we show three alternative ways to deal with the chapter. The first case
-expands the \XML\ reference so that we have an \XML\ stream in the auxiliary
-file. This stream is processed as a small independent subfile when needed. The
-second case registers a reference to the current element (\type {#1}). This means
-that we have access to all data of this element, like attributes, title and
-content. What happens depends on the given setup. The third variant does the same
-but here the setup is part of the reference.
-
-\starttyping
-\startxmlsetups xml:chapter
- \ifcase \TestMode
- % xml code travels around
- \setuphead[chapter][expansion=xml]
- \startchapter[title=eh: \xmltext{#1}{title}]
- \xmlfirst{#1}{content}
- \stopchapter
- \or
- % index is used for access via setup
- \setuphead[chapter][expansion=yes,xmlsetup=xml:title:flush]
- \startchapter[title=\xmlgetindex{#1}]
- \xmlfirst{#1}{content}
- \stopchapter
- \or
- % tex call to xml using index is used
- \setuphead[chapter][expansion=yes]
- \startchapter[title=hm: \xmlreference{#1}{xml:title:flush}]
- \xmlfirst{#1}{content}
- \stopchapter
- \fi
-\stopxmlsetups
-
-\startxmlsetups xml:title:flush
- \xmltext{#1}{title}
-\stopxmlsetups
-\stoptyping
-
-We need to deal with emphasis and the content of the chapter.
-
-\starttyping
-\startxmlsetups xml:em
- \begingroup\em\xmlflush{#1}\endgroup
-\stopxmlsetups
-
-\startxmlsetups xml:content
- \xmlflush{#1}
-\stopxmlsetups
-\stoptyping
-
-A similar approach is followed with the index entries. Watch how we use the
-numbered entries variant (in this case we could also have used just \type
-{entries} and \type {keys}).
-
-\starttyping
-\startxmlsetups xml:index
- \ifcase \TestMode
- \setupregister[index][expansion=xml,xmlsetup=]
- \setstructurepageregister
- [index]
- [entries:1=\xmlfirst{#1}{content},
- keys:1=\xmltext{#1}{key}]
- \or
- \setupregister[index][expansion=yes,xmlsetup=xml:index:flush]
- \setstructurepageregister
- [index]
- [entries:1=\xmlgetindex{#1},
- keys:1=\xmltext{#1}{key}]
- \or
- \setupregister[index][expansion=yes,xmlsetup=]
- \setstructurepageregister
- [index]
- [entries:1=\xmlreference{#1}{xml:index:flush},
- keys:1=\xmltext{#1}{key}]
- \fi
-\stopxmlsetups
-
-\startxmlsetups xml:index:flush
- \xmlfirst{#1}{content}
-\stopxmlsetups
-\stoptyping
-
-Instead of this flush, you can use the predefined setup \type {xml:flush}
-unless it is overloaded by you.
-
-The file is processed by:
-
-\starttyping
-\starttext
- \xmlprocessfile{main}{test.xml}{}
-\stoptext
-\stoptyping
-
-We don't show the result here. If you're curious what the output is, you can test
-it yourself. In that case it also makes sense to peek into the \type {test.tuc}
-file to see how the information travels around. The \type {metadata} fields carry
-information about how to process the data.
-
-The first case, the \XML\ expansion one, is somewhat special in the sense that
-internally we use small pseudo files. You can control the rendering by tweaking
-the following setups:
-
-\starttyping
-\startxmlsetups xml:ctx:sectionentry
- \xmlflush{#1}
-\stopxmlsetups
-
-\startxmlsetups xml:ctx:registerentry
- \xmlflush{#1}
-\stopxmlsetups
-\stoptyping
-
-{\em When these methods work out okay the other structural elements will be
-dealt with in a similar way.}
-
-\stopsection
-
-\startsection[title={special cases}]
-
-Normally the content will be flushed under a special (so called) catcode regime.
-This means that characters that have a special meaning in \TEX\ will have no such
-meaning in an \XML\ file. If you want content to be treated as \TEX\ code, you can
-use one of the following:
-
-\startxmlcmd {\cmdbasicsetup{xmlflushcontext}}
- flush the given \cmdinternal {cd:node} using the \TEX\ character
- interpretation scheme
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlcontext}}
- flush the match of \cmdinternal {cd:lpath} for the given \cmdinternal
- {cd:node} using the \TEX\ character interpretation scheme
-\stopxmlcmd
-
-We use this in cases like:
-
-\starttyping
-....
- \xmlsetsetup {#1} {
- tm|texformula|
- } {xml:*}
-....
-
-\startxmlsetups xml:tm
- \mathematics{\xmlflushcontext{#1}}
-\stopxmlsetups
-
-\startxmlsetups xml:texformula
- \placeformula\startformula\xmlflushcontext{#1}\stopformula
-\stopxmlsetups
-\stoptyping
-
-\stopsection
-
-\startsection[title={collecting}]
-
-Say that your document has
-
-\starttyping
-<table>
- <tr>
- <td>foo</td>
- <td>bar<td>
- </tr>
-</table>
-\stoptyping
-
-And that you need to convert that to \TEX\ speak like:
-
-\starttyping
-\bTABLE
- \bTR
- \bTD foo \eTD
- \bTD bar \eTD
- \eTR
-\eTABLE
-\stoptyping
-
-A simple mapping is:
-
-\starttyping
-\startxmlsetups xml:table
- \bTABLE \xmlflush{#1} \eTABLE
-\stopxmlsetups
-\startxmlsetups xml:tr
- \bTR \xmlflush{#1} \eTR
-\stopxmlsetups
-\startxmlsetups xml:td
- \bTD \xmlflush{#1} \eTD
-\stopxmlsetups
-\stoptyping
-
-The \type {\bTD} command is a so called delimited command which means that it
-picks up its argument by looking for an \type {\eTD}. For the simple case here
-this works quite well because the flush is inside the pair. This is not the case
-in the following variant:
-
-\starttyping
-\startxmlsetups xml:td:start
- \bTD
-\stopxmlsetups
-\startxmlsetups xml:td:stop
- \eTD
-\stopxmlsetups
-\startxmlsetups xml:td
- \xmlsetup{#1}{xml:td:start}
- \xmlflush{#1}
- \xmlsetup{#1}{xml:td:stop}
-\stopxmlsetups
-\stoptyping
-
-When for some reason \TEX\ gets confused you can revert to a mechanism that
-collects content.
-
-\starttyping
-\startxmlsetups xml:td:start
- \startcollect
- \bTD
- \stopcollect
-\stopxmlsetups
-\startxmlsetups xml:td:stop
- \startcollect
- \eTD
- \stopcollect
-\stopxmlsetups
-\startxmlsetups xml:td
- \startcollecting
- \xmlsetup{#1}{xml:td:start}
- \xmlflush{#1}
- \xmlsetup{#1}{xml:td:stop}
- \stopcollecting
-\stopxmlsetups
-\stoptyping
-
-You can even implement solutions that effectively do this:
-
-\starttyping
-\startcollecting
- \startcollect \bTABLE \stopcollect
- \startcollect \bTR \stopcollect
- \startcollect \bTD \stopcollect
- \startcollect foo\stopcollect
- \startcollect \eTD \stopcollect
- \startcollect \bTD \stopcollect
- \startcollect bar\stopcollect
- \startcollect \eTD \stopcollect
- \startcollect \eTR \stopcollect
- \startcollect \eTABLE \stopcollect
-\stopcollecting
-\stoptyping
-
-Of course you only need to go that complex when the situation demands it. Here is
-another weird one:
-
-\starttyping
-\startcollecting
- \startcollect \setupsomething[\stopcollect
- \startcollect foo=\stopcollect
- \startcollect FOO,\stopcollect
- \startcollect bar=\stopcollect
- \startcollect BAR,\stopcollect
- \startcollect ]\stopcollect
-\stopcollecting
-\stoptyping
-
-\stopsection
-
-\startsection[title={selectors and injectors}]
-
-This section describes a bit special feature, one that we needed for a project
-where we could not touch the original content but could add specific sections for
-our own purpose. Hopefully the example demonstrates its useability.
-
-\enabletrackers[lxml.selectors]
-
-\startbuffer[foo]
-<?xml version="1.0" encoding="UTF-8"?>
-
-<?context-directive message info 1: this is a demo file ?>
-<?context-message-directive info 2: this is a demo file ?>
-
-<one>
- <two>
- <?context-select begin t1 t2 t3 ?>
- <three>
- t1 t2 t3
- <?context-directive injector crlf t1 ?>
- t1 t2 t3
- </three>
- <?context-select end ?>
- <?context-select begin t4 ?>
- <four>
- t4
- </four>
- <?context-select end ?>
- <?context-select begin t8 ?>
- <four>
- t8.0
- t8.0
- </four>
- <?context-select end ?>
- <?context-include begin t4 ?>
- <!--
- <three>
- t4.t3
- <?context-directive injector crlf t1 ?>
- t4.t3
- </three>
- -->
- <three>
- t3
- <?context-directive injector crlf t1 ?>
- t3
- </three>
- <?context-include end ?>
- <?context-select begin t8 ?>
- <four>
- t8.1
- t8.1
- </four>
- <?context-select end ?>
- <?context-select begin t8 ?>
- <four>
- t8.2
- t8.2
- </four>
- <?context-select end ?>
- <?context-select begin t4 ?>
- <four>
- t4
- t4
- </four>
- <?context-select end ?>
- <?context-directive injector page t7 t8 ?>
- foo
- <?context-directive injector blank t1 ?>
- bar
- <?context-directive injector page t7 t8 ?>
- bar
- </two>
-</one>
-\stopbuffer
-
-\typebuffer[foo]
-
-First we show how to plug in a directive. Processing instructions like the
-following are normally ignored by an \XML\ processor, unless they make sense
-to it.
-
-\starttyping
-<?context-directive message info 1: this is a demo file ?>
-<?context-message-directive info 2: this is a demo file ?>
-\stoptyping
-
-We can define a message handler as follows:
-
-\startbuffer
-\def\MyMessage#1#2#3{\writestatus{#1}{#2 #3}}
-
-\xmlinstalldirective{message}{MyMessage}
-\stopbuffer
-
-\typebuffer \getbuffer
-
-When this file is processed you will see this on the console:
-
-\starttyping
-info > 1: this is a demo file
-info > 2: this is a demo file
-\stoptyping
-
-The file has some sections that can be used or ignored. The recipe for
-obeying \type {t1} and \type {t4} is the following:
-
-\startbuffer
-\xmlsetinjectors[t1]
-\xmlsetinjectors[t4]
-
-\startxmlsetups xml:initialize
- \xmlapplyselectors{#1}
- \xmlsetsetup {#1} {
- one|two|three|four
- } {xml:*}
-\stopxmlsetups
-
-\xmlregistersetup{xml:initialize}
-
-\startxmlsetups xml:one
- [ONE \xmlflush{#1} ONE]
-\stopxmlsetups
-
-\startxmlsetups xml:two
- [TWO \xmlflush{#1} TWO]
-\stopxmlsetups
-
-\startxmlsetups xml:three
- [THREE \xmlflush{#1} THREE]
-\stopxmlsetups
-
-\startxmlsetups xml:four
- [FOUR \xmlflush{#1} FOUR]
-\stopxmlsetups
-\stopbuffer
-
-\typebuffer \getbuffer
-
-This typesets:
-
-\startnarrower
-\xmlprocessbuffer{main}{foo}{}
-\stopnarrower
-
-The include coding is kind of special: it permits adding content (in a comment)
-and ignoring the rest so that we indeed can add something without interfering
-with the original. Of course in a normal workflow such messy solutions are
-not needed, but alas, often workflows are not that clean, especially when one
-has no real control over the source.
-
-\startxmlcmd {\cmdbasicsetup{xmlsetinjectors}}
- enables a list of injectors that will be used
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlresetinjectors}}
- resets the list of injectors
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlinjector}}
- expands an injection (command); normally this one is only used
- (in some setup) or for testing
-\stopxmlcmd
-
-\startxmlcmd {\cmdbasicsetup{xmlapplyselectors}}
- analyze the tree \cmdinternal {cd:node} for marked sections that
- will be injected
-\stopxmlcmd
-
-We have some injections predefined:
-
-\starttyping
-\startsetups xml:directive:injector:page
- \page
-\stopsetups
-
-\startsetups xml:directive:injector:column
- \column
-\stopsetups
-
-\startsetups xml:directive:injector:blank
- \blank
-\stopsetups
-\stoptyping
-
-In the example we see:
-
-\starttyping
-<?context-directive injector page t7 t8 ?>
-\stoptyping
-
-When we set \type {\xmlsetinjector[t7]} a pagebreak will injected in that spot.
-Tags like \type {t7}, \type {t8} etc.\ can represent versions.
-
-\stopsection
-
-\startsection[title=preprocessing]
-
-% local match = lpeg.match
-% local replacer = lpeg.replacer("BAD TITLE:","<bold>BAD TITLE:</bold>")
-%
-% function lxml.preprocessor(data,settings)
-% return match(replacer,data)
-% end
-
-\startbuffer[pre-code]
-\startluacode
- function lxml.preprocessor(data,settings)
- return string.find(data,"BAD TITLE:")
- and string.gsub(data,"BAD TITLE:","<bold>BAD TITLE:</bold>")
- or data
- end
-\stopluacode
-\stopbuffer
-
-\startbuffer[pre-xml]
-\startxmlsetups pre:demo:initialize
- \xmlsetsetup{#1}{*}{pre:demo:*}
-\stopxmlsetups
-
-\xmlregisterdocumentsetup{pre:demo}{pre:demo:initialize}
-
-\startxmlsetups pre:demo:root
- \xmlflush{#1}
-\stopxmlsetups
-
-\startxmlsetups pre:demo:bold
- \begingroup\bf\xmlflush{#1}\endgroup
-\stopxmlsetups
-
-\starttext
- \xmlprocessbuffer{pre:demo}{demo}{}
-\stoptext
-\stopbuffer
-
-Say that you have the following \XML\ setup:
-
-\typebuffer[pre-xml]
-
-and that (such things happen) the input looks like this:
-
-\startbuffer[demo]
-<root>
-BAD TITLE: crap crap crap ...
-
-BAD TITLE: crap crap crap ...
-</root>
-\stopbuffer
-
-\typebuffer[demo]
-
-You can then clean up these \type {BAD TITLE}'s as follows:
-
-\typebuffer[pre-code]
-
-and get as result:
-
-\start \getbuffer[pre-code,pre-xml] \stop
-
-The preprocessor function gets as second argument the current settings, an d
-the field \type {currentresource} can be used to limit the actions to
-specific resources, in our case it's \type {buffer: demo}. Afterwards you can
-reset the proprocessor with:
-
-\startluacode
-lxml.preprocessor = nil
-\stopluacode
-
-Future versions might give some more control over preprocessors. For now consider
-it to be a quick hack.
-
-\stopsection
-
-\stopchapter
-
-\startchapter[title={Lookups using lpaths}]
-
-\startsection[title={introduction}]
-
-There is not that much system in the following examples. They resulted from tests
-with different documents. The current implementation evolved out of the
-experimental code. For instance, I decided to add the multiple expressions in row
-handling after a few email exchanges with Jean|-|Michel Huffen.
-
-One of the main differences between the way \XSLT\ resolves a path and our way is
-the anchor. Take:
-
-\starttyping
-/something
-something
-\stoptyping
-
-The first one anchors in the current (!) element so it will only consider direct
-children. The second one does a deep lookup and looks at the descendants as well.
-Furthermore we have a few extra shortcuts like \type {**} in \type {a/**/b} which
-represents all descendants.
-
-The expressions (between square brackets) has to be valid \LUA\ and some
-preprocessing is done to resolve the built in functions. So, you might use code
-like:
-
-\starttyping
-my_lpeg_expression:match(text()) == "whatever"
-\stoptyping
-
-given that \type {my_lpeg_expression} is known. In the examples below we use the
-visualizer to show the steps. Some are shown more than once as part of a set.
-
-\stopsection
-
-\startsection[title={special cases}]
-
-\xmllshow{}
-\xmllshow{*}
-\xmllshow{.}
-\xmllshow{/}
-
-\stopsection
-
-\startsection[title={wildcards}]
-
-\xmllshow{*}
-\xmllshow{*:*}
-\xmllshow{/*}
-\xmllshow{/*:*}
-\xmllshow{*/*}
-\xmllshow{*:*/*:*}
-
-\xmllshow{a/*}
-\xmllshow{a/*:*}
-\xmllshow{/a/*}
-\xmllshow{/a/*:*}
-
-\xmllshow{/*}
-\xmllshow{/**}
-\xmllshow{/***}
-
-\stopsection
-
-\startsection[title={multiple steps}]
-
-\xmllshow{answer}
-\xmllshow{answer/test/*}
-\xmllshow{answer/test/child::}
-\xmllshow{answer/*}
-\xmllshow{answer/*[tag()='p' and position()=1 and text()!='']}
-
-\stopsection
-
-\startsection[title={pitfals}]
-
-\xmllshow{[oneof(lower(@encoding),'tex','context','ctx')]}
-\xmllshow{.[oneof(lower(@encoding),'tex','context','ctx')]}
-
-\stopsection
-
-\startsection[title={more special cases}]
-
-\xmllshow{**}
-\xmllshow{*}
-\xmllshow{..}
-\xmllshow{.}
-\xmllshow{//}
-\xmllshow{/}
-
-\xmllshow{**/}
-\xmllshow{**/*}
-\xmllshow{**/.}
-\xmllshow{**//}
-
-\xmllshow{*/}
-\xmllshow{*/*}
-\xmllshow{*/.}
-\xmllshow{*//}
-
-\xmllshow{/**/}
-\xmllshow{/**/*}
-\xmllshow{/**/.}
-\xmllshow{/**//}
-
-\xmllshow{/*/}
-\xmllshow{/*/*}
-\xmllshow{/*/.}
-\xmllshow{/*//}
-
-\xmllshow{./}
-\xmllshow{./*}
-\xmllshow{./.}
-\xmllshow{.//}
-
-\xmllshow{../}
-\xmllshow{../*}
-\xmllshow{../.}
-\xmllshow{..//}
-
-\stopsection
-
-\startsection[title={more wildcards}]
-
-\xmllshow{one//two}
-\xmllshow{one/*/two}
-\xmllshow{one/**/two}
-\xmllshow{one/***/two}
-\xmllshow{one/x//two}
-\xmllshow{one//x/two}
-\xmllshow{//x/two}
-
-\stopsection
-
-\startsection[title={special axis}]
-
-\xmllshow{descendant::whocares/ancestor::whoknows}
-\xmllshow{descendant::whocares/ancestor::whoknows/parent::}
-\xmllshow{descendant::whocares/ancestor::}
-\xmllshow{child::something/child::whatever/child::whocares}
-\xmllshow{child::something/child::whatever/child::whocares|whoknows}
-\xmllshow{child::something/child::whatever/child::(whocares|whoknows)}
-\xmllshow{child::something/child::whatever/child::!(whocares|whoknows)}
-\xmllshow{child::something/child::whatever/child::(whocares)}
-\xmllshow{child::something/child::whatever/child::(whocares)[position()>2]}
-\xmllshow{child::something/child::whatever[position()>2][position()=1]}
-\xmllshow{child::something/child::whatever[whocares][whocaresnot]}
-\xmllshow{child::something/child::whatever[whocares][not(whocaresnot)]}
-\xmllshow{child::something/child::whatever/self::whatever}
-
-There is also \type {last-match::} that starts with the last found set of nodes.
-This can save some run time when you do lots of tests combined with a same check
-afterwards. There is however one pitfall: you never know what is done with that
-last match in the setup that gets called nested. Take the following example:
-
-\starttyping
-\startbuffer[test]
-<something>
- <crap> <crapa> <crapb> <crapc> <crapd>
- <crape>
- done 1
- </crape>
- </crapd> </crapc> </crapb> </crapa>
- <crap> <crapa> <crapb> <crapc> <crapd>
- <crape>
- done 2
- </crape>
- </crapd> </crapc> </crapb> </crapa>
- <crap> <crapa> <crapb> <crapc> <crapd>
- <crape>
- done 3
- </crape>
- </crapd> </crapc> </crapb> </crapa>
-</something>
-\stopbuffer
-\stoptyping
-
-One way to filter the content is this:
-
-\starttyping
-\xmldoif {#1} {/crap/crapa/crapb/crapc/crapd/crape} {
- some action
-}
-\stoptyping
-
-It is not unlikely that you will do something like this:
-
-\starttyping
-\xmlfirst {#1} {/crap/crapa/crapb/crapc/crapd/crape} {
- \xmlfirst{#1}{/crap/crapa/crapb/crapc/crapd/crape}
-}
-\stoptyping
-
-This means that the path is resolved twice but that can be avoided as
-follows:
-
-\starttyping
-\xmldoif{#1}{/crap/crapa/crapb/crapc/crapd/crape}{
- \xmlfirst{#1}{last-match::}
-}
-\stoptyping
-
-But the next is now guaranteed to work:
-
-\starttyping
-\xmldoif{#1}{/crap/crapa/crapb/crapc/crapd/crape}{
- \xmlfirst{#1}{last-match::}
- \xmllast{#1}{last-match::}
-}
-\stoptyping
-
-Because the first one can have done some lookup the last match can be replaced
-and the second call will give unexpected results. You can overcome this with:
-
-\starttyping
-\xmldoif{#1}{/crap/crapa/crapb/crapc/crapd/crape}{
- \xmlpushmatch
- \xmlfirst{#1}{last-match::}
- \xmlpopmatch
-}
-\stoptyping
-
-Does it pay off? Here are some timings of a 10.000 times text and lookup
-like the previous (on a decent January 2016 laptop):
-
-\starttabulate[|r|l|]
-\NC 0.239 \NC \type {\xmldoif {...} {...}} \NC \NR
-\NC 0.292 \NC \type {\xmlfirst {...} {...}} \NC \NR
-\NC 0.538 \NC \type {\xmldoif {...} {...} + \xmlfirst {...} {...}} \NC \NR
-\NC 0.338 \NC \type {\xmldoif {...} {...} + \xmlfirst {...} {last-match::}} \NC \NR
-\NC 0.349 \NC \type {+ \xmldoif {...} {...} + \xmlfirst {...} {last-match::}-} \NC \NR
-\stoptabulate
-
-So, pushing and popping (the last row) is a bit slower than not doing that but it
-is still much faster than not using \type {last-match::} at all. As a shortcut
-you can use \type {=}, as in:
-
-\starttyping
-\xmlfirst{#1}{=}
-\stoptyping
-
-You can even do this:
-
-\starttyping
-\xmlall{#1}{last-match::/text()}
-\stoptyping
-
-or
-
-\starttyping
-\xmlall{#1}{=/text()}
-\stoptyping
-
-
-\stopsection
-
-\startsection[title={some more examples}]
-
-\xmllshow{/something/whatever}
-\xmllshow{something/whatever}
-\xmllshow{/**/whocares}
-\xmllshow{whoknows/whocares}
-\xmllshow{whoknows}
-\xmllshow{whocares[contains(text(),'f') or contains(text(),'g')]}
-\xmllshow{whocares/first()}
-\xmllshow{whocares/last()}
-\xmllshow{whatever/all()}
-\xmllshow{whocares/position(2)}
-\xmllshow{whocares/position(-2)}
-\xmllshow{whocares[1]}
-\xmllshow{whocares[-1]}
-\xmllshow{whocares[2]}
-\xmllshow{whocares[-2]}
-\xmllshow{whatever[3]/attribute(id)}
-\xmllshow{whatever[2]/attribute('id')}
-\xmllshow{whatever[3]/text()}
-\xmllshow{/whocares/first()}
-\xmllshow{/whocares/last()}
-
-\xmllshow{xml://whatever/all()}
-\xmllshow{whatever/all()}
-\xmllshow{//whocares}
-\xmllshow{..[2]}
-\xmllshow{../*[2]}
-
-\xmllshow{/(whocares|whocaresnot)}
-\xmllshow{/!(whocares|whocaresnot)}
-\xmllshow{/!whocares}
-
-\xmllshow{/interface/command/command(xml:setups:register)}
-\xmllshow{/interface/command[@name='xxx']/command(xml:setups:typeset)}
-\xmllshow{/arguments/*}
-\xmllshow{/sequence/first()}
-\xmllshow{/arguments/text()}
-\xmllshow{/sequence/variable/first()}
-\xmllshow{/interface/define[@name='xxx']/first()}
-\xmllshow{/parameter/command(xml:setups:parameter:measure)}
-
-\xmllshow{/(*:library|figurelibrary)/*:figure/*:label}
-\xmllshow{/(*:library|figurelibrary)/figure/*:label}
-\xmllshow{/(*:library|figurelibrary)/figure/label}
-\xmllshow{/(*:library|figurelibrary)/figure:*/label}
-
-\xmlshow {whatever//br[tag(1)='br']}
-
-\stopsection
-
-\stopchapter
-
-\startchapter[title=Examples]
-
-\startsection[title=attribute chains]
-
-In \CSS, when an attribute is not present, the parent element is checked, and when
-not found again, the lookup follows the chain till a match is found or the root is
-reached. The following example demonstrates how such a chain lookup works.
-
-\startbuffer[test]
-<something mine="1" test="one" more="alpha">
- <whatever mine="2" test="two">
- <whocares mine="3">
- <!-- this is a test -->
- </whocares>
- </whatever>
-</something>
-\stopbuffer
-
-\typebuffer[test]
-
-We apply the following setups to this tree:
-
-\startbuffer[setups]
-\startxmlsetups xml:common
- [
- \xmlchainatt{#1}{mine},
- \xmlchainatt{#1}{test},
- \xmlchainatt{#1}{more},
- \xmlchainatt{#1}{none}
- ]\par
-\stopxmlsetups
-
-\startxmlsetups xml:something
- something: \xmlsetup{#1}{xml:common}
- \xmlflush{#1}
-\stopxmlsetups
-
-\startxmlsetups xml:whatever
- whatever: \xmlsetup{#1}{xml:common}
- \xmlflush{#1}
-\stopxmlsetups
-
-\startxmlsetups xml:whocares
- whocares: \xmlsetup{#1}{xml:common}
- \xmlflush{#1}
-\stopxmlsetups
-
-\startxmlsetups xml:mysetups
- \xmlsetsetup{#1}{something|whatever|whocares}{xml:*}
-\stopxmlsetups
-
-\xmlregisterdocumentsetup{example-1}{xml:mysetups}
-
-\xmlprocessbuffer{example-1}{test}{}
-\stopbuffer
-
-\typebuffer[setups]
-
-This gives:
-
-\start
- \getbuffer[setups]
-\stop
-
-\stopsection
-
-\startsection[title=conditional setups]
-
-Say that we have this code:
-
-\starttyping
-\xmldoifelse {#1} {/what[@a='1']} {
- \xmlfilter {#1} {/what/command('xml:yes')}
-} {
- \xmlfilter {#1} {/what/command('xml:nop')}
-}
-\stoptyping
-
-Here we first determine if there is a child \type {what} with attribute \type {a}
-set to \type {1}. Depending on the outcome again we check the child nodes for
-being named \type {what}. A faster solution which also takes less code is this:
-
-\starttyping
-\xmlfilter {#1} {/what[@a='1']/command('xml:yes','xml:nop')}
-\stoptyping
-
-\stopsection
-
-\startsection[title=manipulating]
-
-Assume that we have the following \XML\ data:
-
-\startbuffer[test]
-<A>
- <B>right</B>
- <B>wrong</B>
-</A>
-\stopbuffer
-
-\typebuffer[test]
-
-But, instead of \type {right} we want to see \type {okay}. We can do that with a
-finalizer:
-
-\startbuffer
-\startluacode
-local rehash = {
- ["right"] = "okay",
-}
-
-function xml.finalizers.tex.Okayed(collected,what)
- for i=1,#collected do
- if what == "all" then
- local str = xml.text(collected[i])
- context(rehash[str] or str)
- else
- context(str)
- end
- end
-end
-\stopluacode
-\stopbuffer
-
-\typebuffer \getbuffer
-
-\startbuffer
-\startxmlsetups xml:A
- \xmlflush{#1}
-\stopxmlsetups
-
-\startxmlsetups xml:B
- (It's \xmlfilter{#1}{./Okayed("all")})
-\stopxmlsetups
-
-\startxmlsetups xml:testsetups
- \xmlsetsetup{#1}{A|B}{xml:*}
-\stopxmlsetups
-
-\xmlregisterdocumentsetup{example-2}{xml:testsetups}
-\xmlprocessbuffer{example-2}{test}{}
-\stopbuffer
-
-\typebuffer
-
-The result is: \start \inlinebuffer \stop
-
-\stopsection
-
-\startsection[title=cross referencing]
-
-A rather common way to add cross references to \XML\ files is to borrow the
-asymmetrical id's from \HTML. This means that one cannot simply use a value
-of (say) \type {href} to locate an \type {id}. The next example came up on
-the \CONTEXT\ mailing list.
-
-\startbuffer[test]
-<doc>
- <p>Text
- <a href="#fn1" class="footnoteref" id="fnref1"><sup>1</sup></a> and
- <a href="#fn2" class="footnoteref" id="fnref2"><sup>2</sup></a>
- </p>
- <div class="footnotes">
- <hr />
- <ol>
- <li id="fn1"><p>A footnote.<a href="#fnref1">↩</a></p></li>
- <li id="fn2"><p>A second footnote.<a href="#fnref2">↩</a></p></li>
- </ol>
- </div>
-</doc>
-\stopbuffer
-
-\typebuffer[test]
-
-We give two variants for dealing with such references. The first solution does
-lookups and depending on the size of the file can be somewhat inefficient.
-
-\startbuffer
-\startxmlsetups xml:doc
- \blank
- \xmlflush{#1}
- \blank
-\stopxmlsetups
-
-\startxmlsetups xml:p
- \xmlflush{#1}
-\stopxmlsetups
-
-\startxmlsetups xml:footnote
- (variant 1)\footnote
- {\xmlfirst
- {example-3-1}
- {div[@class='footnotes']/ol/li[@id='\xmlrefatt{#1}{href}']}}
-\stopxmlsetups
-
-\startxmlsetups xml:initialize
- \xmlsetsetup{#1}{p|doc}{xml:*}
- \xmlsetsetup{#1}{a[@class='footnoteref']}{xml:footnote}
- \xmlsetsetup{#1}{div[@class='footnotes']}{xml:nothing}
-\stopxmlsetups
-
-\xmlresetdocumentsetups{*}
-\xmlregisterdocumentsetup{example-3-1}{xml:initialize}
-
-\xmlprocessbuffer{example-3-1}{test}{}
-\stopbuffer
-
-\typebuffer
-
-This will typeset two footnotes.
-
-\getbuffer
-
-The second variant collects the references so that the time spend on lookups is
-less.
-
-\startbuffer
-\startxmlsetups xml:doc
- \blank
- \xmlflush{#1}
- \blank
-\stopxmlsetups
-
-\startxmlsetups xml:p
- \xmlflush{#1}
-\stopxmlsetups
-
-\startluacode
- userdata.notes = {}
-\stopluacode
-
-\startxmlsetups xml:collectnotes
- \ctxlua{userdata.notes['\xmlrefatt{#1}{id}'] = '#1'}
-\stopxmlsetups
-
-\startxmlsetups xml:footnote
- (variant 2)\footnote
- {\xmlflush
- {\cldcontext{userdata.notes['\xmlrefatt{#1}{href}']}}}
-\stopxmlsetups
-
-\startxmlsetups xml:initialize
- \xmlsetsetup{#1}{p|doc}{xml:*}
- \xmlsetsetup{#1}{a[@class='footnoteref']}{xml:footnote}
- \xmlfilter{#1}{div[@class='footnotes']/ol/li/command(xml:collectnotes)}
- \xmlsetsetup{#1}{div[@class='footnotes']}{}
-\stopxmlsetups
-
-\xmlregisterdocumentsetup{example-3-2}{xml:initialize}
-
-\xmlprocessbuffer{example-3-2}{test}{}
-\stopbuffer
-
-\typebuffer
-
-This will again typeset two footnotes:
-
-\getbuffer
-
-\stopsection
-
-\startsection[title=mapping values]
-
-One way to process options \type {frame} in the example below is to map the
-values to values known by \CONTEXT.
-
-\startbuffer[test]
-<a>
- <nattable frame="on">
- <tr><td>#1</td><td>#2</td><td>#3</td><td>#4</td></tr>
- <tr><td>#5</td><td>#6</td><td>#7</td><td>#8</td></tr>
- </nattable>
- <nattable frame="off">
- <tr><td>#1</td><td>#2</td><td>#3</td><td>#4</td></tr>
- <tr><td>#5</td><td>#6</td><td>#7</td><td>#8</td></tr>
- </nattable>
- <nattable frame="no">
- <tr><td>#1</td><td>#2</td><td>#3</td><td>#4</td></tr>
- <tr><td>#5</td><td>#6</td><td>#7</td><td>#8</td></tr>
- </nattable>
-</a>
-\stopbuffer
-
-\typebuffer[test]
-
-\startbuffer
-\startxmlsetups xml:a
- \xmlflush{#1}
-\stopxmlsetups
-
-\xmlmapvalue {nattable:frame} {on} {on}
-\xmlmapvalue {nattable:frame} {yes} {on}
-\xmlmapvalue {nattable:frame} {off} {off}
-\xmlmapvalue {nattable:frame} {no} {off}
-
-\startxmlsetups xml:nattable
- \startplacetable[title=#1]
- \setupTABLE[frame=\xmlval{nattable:frame}{\xmlatt{#1}{frame}}{on}]%
- \bTABLE
- \xmlflush{#1}
- \eTABLE
- \stopplacetable
-\stopxmlsetups
-
-\startxmlsetups xml:tr
- \bTR
- \xmlflush{#1}
- \eTR
-\stopxmlsetups
-
-\startxmlsetups xml:td
- \bTD
- \xmlflush{#1}
- \eTD
-\stopxmlsetups
-
-\startxmlsetups xml:testsetups
- \xmlsetsetup{example-4}{a|nattable|tr|td|}{xml:*}
-\stopxmlsetups
-
-\xmlregisterdocumentsetup{example-4}{xml:testsetups}
-
-\xmlprocessbuffer{example-4}{test}{}
-\stopbuffer
-
-The \type {\xmlmapvalue} mechanism is rather efficient and involves a minimum
-of testing.
-
-\typebuffer
-
-We get:
-
-\getbuffer
-
-\stopsection
-
-\startsection[title=using \LUA]
-
-In this example we demonstrate how you can delegate rendering to \LUA. We
-will construct a so called extreme table. The input is:
-
-\startbuffer[demo]
-<?xml version="1.0" encoding="utf-8"?>
-
-<a>
- <b> <c>1</c> <d>Text</d> </b>
- <b> <c>2</c> <d>More text</d> </b>
- <b> <c>2</c> <d>Even more text</d> </b>
- <b> <c>2</c> <d>And more</d> </b>
- <b> <c>3</c> <d>And even more</d> </b>
- <b> <c>2</c> <d>The last text</d> </b>
-</a>
-\stopbuffer
-
-\typebuffer[demo]
-
-The processor code is:
-
-\startbuffer[process]
-\startxmlsetups xml:test_setups
- \xmlsetsetup{#1}{a|b|c|d}{xml:*}
-\stopxmlsetups
-
-\xmlregisterdocumentsetup{example-5}{xml:test_setups}
-
-\xmlprocessbuffer{example-5}{demo}{}
-\stopbuffer
-
-\typebuffer
-
-We color a sequence of the same titles (numbers here) differently. The first
-solution remembers the last title:
-
-\startbuffer
-\startxmlsetups xml:a
- \startembeddedxtable
- \xmlflush{#1}
- \stopembeddedxtable
-\stopxmlsetups
-
-\startxmlsetups xml:b
- \xmlfunction{#1}{test_ba}
-\stopxmlsetups
-
-\startluacode
-local lasttitle = nil
-
-function xml.functions.test_ba(t)
- local title = xml.text(t, "/c")
- local content = xml.text(t, "/d")
- context.startxrow()
- context.startxcell {
- background = "color",
- backgroundcolor = lasttitle == title and "colorone" or "colortwo",
- foregroundstyle = "bold",
- foregroundcolor = "white",
- }
- context(title)
- lasttitle = title
- context.stopxcell()
- context.startxcell()
- context(content)
- context.stopxcell()
- context.stopxrow()
-end
-\stopluacode
-\stopbuffer
-
-\typebuffer \getbuffer
-
-The \type {embeddedxtable} environment is needed because the table is picked up
-as argument.
-
-\startlinecorrection \getbuffer[process] \stoplinecorrection
-
-The second implemetation remembers what titles are already processed so here we
-can color the last one too.
-
-\startbuffer
-\startxmlsetups xml:a
- \ctxlua{xml.functions.reset_bb()}
- \startembeddedxtable
- \xmlflush{#1}
- \stopembeddedxtable
-\stopxmlsetups
-
-\startxmlsetups xml:b
- \xmlfunction{#1}{test_bb}
-\stopxmlsetups
-
-\startluacode
-local titles
-
-function xml.functions.reset_bb(t)
- titles = { }
-end
-
-function xml.functions.test_bb(t)
- local title = xml.text(t, "/c")
- local content = xml.text(t, "/d")
- context.startxrow()
- context.startxcell {
- background = "color",
- backgroundcolor = titles[title] and "colorone" or "colortwo",
- foregroundstyle = "bold",
- foregroundcolor = "white",
- }
- context(title)
- titles[title] = true
- context.stopxcell()
- context.startxcell()
- context(content)
- context.stopxcell()
- context.stopxrow()
-end
-\stopluacode
-\stopbuffer
-
-\typebuffer \getbuffer
-
-\startlinecorrection \getbuffer[process] \stoplinecorrection
-
-A solution without any state variable is given below.
-
-\startbuffer
-\startxmlsetups xml:a
- \startembeddedxtable
- \xmlflush{#1}
- \stopembeddedxtable
-\stopxmlsetups
-
-\startxmlsetups xml:b
- \xmlfunction{#1}{test_bc}
-\stopxmlsetups
-
-\startluacode
-function xml.functions.test_bc(t)
- local title = xml.text(t, "/c")
- local content = xml.text(t, "/d")
- context.startxrow()
- local okay = xml.text(t,"./preceding-sibling::/[-1]") == title
- context.startxcell {
- background = "color",
- backgroundcolor = okay and "colorone" or "colortwo",
- foregroundstyle = "bold",
- foregroundcolor = "white",
- }
- context(title)
- context.stopxcell()
- context.startxcell()
- context(content)
- context.stopxcell()
- context.stopxrow()
-end
-\stopluacode
-\stopbuffer
-
-\typebuffer \getbuffer
-
-\startlinecorrection \getbuffer[process] \stoplinecorrection
-
-Here is a solution that delegates even more to \LUA. The previous variants were
-actually not that safe with repect to special characters and didn't handle
-nested elements either but the next one does.
-
-\startbuffer[demo]
-<?xml version="1.0" encoding="utf-8"?>
-
-<a>
- <b> <c>#1</c> <d>Text</d> </b>
- <b> <c>#2</c> <d>More text</d> </b>
- <b> <c>#2</c> <d>Even more text</d> </b>
- <b> <c>#2</c> <d>And more</d> </b>
- <b> <c>#3</c> <d>And even more</d> </b>
- <b> <c>#2</c> <d>Something <i>nested</i> </d> </b>
-</a>
-\stopbuffer
-
-\typebuffer[demo]
-
-We also need to map the \type {i} element.
-
-\startbuffer
-\startxmlsetups xml:a
- \starttexcode
- \xmlfunction{#1}{test_a}
- \stoptexcode
-\stopxmlsetups
-
-\startxmlsetups xml:c
- \xmlflush{#1}
-\stopxmlsetups
-
-\startxmlsetups xml:d
- \xmlflush{#1}
-\stopxmlsetups
-
-\startxmlsetups xml:i
- {\em\xmlflush{#1}}
-\stopxmlsetups
-
-\startluacode
-function xml.functions.test_a(t)
- context.startxtable()
- local previous = false
- for b in xml.collected(lxml.getid(t),"/b") do
- context.startxrow()
- local current = xml.text(b,"/c")
- context.startxcell {
- background = "color",
- backgroundcolor = (previous == current) and "colorone" or "colortwo",
- foregroundstyle = "bold",
- foregroundcolor = "white",
- }
- lxml.first(b,"/c")
- context.stopxcell()
- context.startxcell()
- lxml.first(b,"/d")
- context.stopxcell()
- previous = current
- context.stopxrow()
- end
- context.stopxtable()
-end
-\stopluacode
-
-\startxmlsetups xml:test_setups
- \xmlsetsetup{#1}{a|b|c|d|i}{xml:*}
-\stopxmlsetups
-
-\xmlregisterdocumentsetup{example-5}{xml:test_setups}
-
-\xmlprocessbuffer{example-5}{demo}{}
-\stopbuffer
-
-\typebuffer
-
-\startlinecorrection \getbuffer \stoplinecorrection
-
-The question is, do we really need \LUA ? Often we don't, apart maybe from an
-occasional special finalizer. A pure \TEX\ solution is given next:
-
-\startbuffer
-\startxmlsetups xml:a
- \glet\MyPreviousTitle\empty
- \glet\MyCurrentTitle \empty
- \startembeddedxtable
- \xmlflush{#1}
- \stopembeddedxtable
-\stopxmlsetups
-
-\startxmlsetups xml:b
- \startxrow
- \xmlflush{#1}
- \stopxrow
-\stopxmlsetups
-
-\startxmlsetups xml:c
- \xdef\MyCurrentTitle{\xmltext{#1}{.}}
- \doifelse {\MyPreviousTitle} {\MyCurrentTitle} {
- \startxcell
- [background=color,
- backgroundcolor=colorone,
- foregroundstyle=bold,
- foregroundcolor=white]
- } {
- \glet\MyPreviousTitle\MyCurrentTitle
- \startxcell
- [background=color,
- backgroundcolor=colortwo,
- foregroundstyle=bold,
- foregroundcolor=white]
- }
- \xmlflush{#1}
- \stopxcell
-\stopxmlsetups
-
-\startxmlsetups xml:d
- \startxcell
- \xmlflush{#1}
- \stopxcell
-\stopxmlsetups
-
-\startxmlsetups xml:i
- {\em\xmlflush{#1}}
-\stopxmlsetups
-
-\startxmlsetups xml:test_setups
- \xmlsetsetup{#1}{*}{xml:*}
-\stopxmlsetups
-
-\xmlregisterdocumentsetup{example-5}{xml:test_setups}
-
-\xmlprocessbuffer{example-5}{demo}{}
-\stopbuffer
-
-\typebuffer
-
-\startlinecorrection \getbuffer \stoplinecorrection
-
-You can even save a few lines of code:
-
-\starttyping
-\startxmlsetups xml:c
- \xdef\MyCurrentTitle{\xmltext{#1}{.}}
- \startxcell
- [background=color,
- backgroundcolor=color\ifx\MyPreviousTitle\MyCurrentTitle one\else two\fi,
- foregroundstyle=bold,
- foregroundcolor=white]
- \xmlflush{#1}
- \stopxcell
- \glet\MyPreviousTitle\MyCurrentTitle
-\stopxmlsetups
-\stoptyping
-
-Or if you prefer:
-
-\starttyping
-\startxmlsetups xml:c
- \xdef\MyCurrentTitle{\xmltext{#1}{.}}
- \doifelse {\MyPreviousTitle} {\MyCurrentTitle} {
- \xmlsetup{#1}{xml:c:one}
- } {
- \xmlsetup{#1}{xml:c:two}
- }
-\stopxmlsetups
-
-\startxmlsetups xml:c:one
- \startxcell
- [background=color,
- backgroundcolor=colorone,
- foregroundstyle=bold,
- foregroundcolor=white]
- \xmlflush{#1}
- \stopxcell
-\stopxmlsetups
-
-\startxmlsetups xml:c:two
- \startxcell
- [background=color,
- backgroundcolor=colortwo,
- foregroundstyle=bold,
- foregroundcolor=white]
- \xmlflush{#1}
- \stopxcell
- \global\let\MyPreviousTitle\MyCurrentTitle
-\stopxmlsetups
-\stoptyping
-
-These examples demonstrate that it doesn't hurt to know a little bit of \TEX\
-programming: defining macros and basic comparisons can come in handy. There are
-examples in the test suite, you can peek in the source code, you can consult
-the wiki or you can just ask on the list.
-
-\stopsection
-
-\startsection[title=last match]
-
-For the next example we use the following \XML\ input:
-
-\startbuffer[demo]
-<?xml version "1.0"?>
-<document>
- <section id="1">
- <content>
- <p>first</p>
- <p>second</p>
- </content>
- </section>
- <section id="2">
- <content>
- <p>third</p>
- <p>fourth</p>
- </content>
- </section>
-</document>
-\stopbuffer
-
-\typebuffer[demo]
-
-If you check if some element is present and then act accordingly, you can
-end up with doing the same lookup twice. Although it might sound inefficient,
-in practice it's often not measureable.
-
-\startbuffer
-\startxmlsetups xml:demo:document
- \type{\xmlall{#1}{/section[@id='2']/content/p}}\par
- \xmldoif{#1}{/section[@id='2']/content/p} {
- \xmlall{#1}{/section[@id='2']/content/p}
- }
- \type{\xmllastmatch}\par
- \xmldoif{#1}{/section[@id='2']/content/p} {
- \xmllastmatch
- }
- \type{\xmlall{#1}{last-match::}}\par
- \xmldoif{#1}{/section[@id='2']/content/p} {
- \xmlall{#1}{last-match::}
- }
- \type{\xmlfilter{#1}{last-match::/command(xml:demo:p)}}\par
- \xmldoif{#1}{/section[@id='2']/content/p} {
- \xmlfilter{#1}{last-match::/command(xml:demo:p)}
- }
-\stopxmlsetups
-
-\startxmlsetups xml:demo:p
- \quad\xmlflush{#1}\endgraf
-\stopxmlsetups
-
-\startxmlsetups xml:demo:base
- \xmlsetsetup{#1}{document|p}{xml:demo:*}
-\stopxmlsetups
-
-\xmlregisterdocumentsetup{example-6}{xml:demo:base}
-
-\xmlprocessbuffer{example-6}{demo}{}
-\stopbuffer
-
-\typebuffer
-
-In the second check we just flush the last match, so effective we do an \type
-{\xmlall} here. The third and fourth alternatives demonstrate how we can use
-\type {last-match} as axis. The gain is 10\% or more on the lookup but of course
-typesetting often takes relatively more time than the lookup.
-
-\startpacked
-\getbuffer
-\stoppacked
-
-\stopsection
-
-\startsection[title=Finalizers]
-
-The \XML\ parser is also available outside \TEX. Here is an example of its usage.
-We pipe the result to \TEX\ but you can do with \type {t} whatever you like.
-
-\startbuffer
-local x = xml.load("manual-demo-1.xml")
-local t = { }
-
-for c in xml.collected(x,"//*") do
- if not c.special and not t[c.tg] then
- t[c.tg] = true
- end
-end
-
-context.tocontext(table.sortedkeys(t))
-\stopbuffer
-
-\typebuffer
-
-This returns:
-
-\ctxluabuffer
-
-We can wrap this in a finalizer:
-
-\startbuffer
-xml.finalizers.taglist = function(collected)
- local t = { }
- for i=1,#collected do
- local c = collected[i]
- if not c.special then
- local tg = c.tg
- if tg and not t[tg] then
- t[tg] = true
- end
- end
- end
- return table.sortedkeys(t)
-end
-\stopbuffer
-
-\typebuffer
-
-Or in a more extensive one:
-
-\startbuffer
-xml.finalizers.taglist = function(collected,parenttoo)
- local t = { }
- for i=1,#collected do
- local c = collected[i]
- if not c.special then
- local tg = c.tg
- if tg and not t[tg] then
- t[tg] = true
- end
- if parenttoo then
- local p = c.__p__
- if p and not p.special then
- local tg = p.tg .. ":" .. tg
- if tg and not t[tg] then
- t[tg] = true
- end
- end
- end
- end
- end
- return table.sortedkeys(t)
-end
-\stopbuffer
-
-\typebuffer \ctxluabuffer
-
-Usage is as follows:
-
-\startbuffer
-local x = xml.load("manual-demo-1.xml")
-local t = xml.applylpath(x,"//*/taglist()")
-
-context.tocontext(t)
-\stopbuffer
-
-\typebuffer
-
-And indeed we get:
-
-\ctxluabuffer
-
-But we can also say:
-
-\startbuffer
-local x = xml.load("manual-demo-1.xml")
-local t = xml.applylpath(x,"//*/taglist(true)")
-
-context.tocontext(t)
-\stopbuffer
-
-\typebuffer
-
-Now we get:
-
-\ctxluabuffer
-
-\startsection[title=Pure xml]
-
-One might wonder how a \TEX\ macro package would look like when backslashes,
-dollars and percent signs would have no special meaning. In fact, it would be
-rather useless as interpreting commands are triggered by such characters. Any
-formatting or coding system needs such characters. Take \XML: angle brackets and
-ampersands are really special. So, no matter what system we use, we do have to
-deal with the (common) case where these characters need to be seen as they are.
-Normally escaping is the solution.
-
-The \CONTEXT\ interface for \XML\ suffers from this as well. You really don't
-want to know how many tricks are used for dealing with special characters and
-entities: there are several ways these travel through the system and it is
-possible to adapt and cheat. Especially roundtripped data (via tuc file) puts
-some demands on the system because when ts \XML\ can become \TEX\ and vise versa.
-The next example (derived from a mail on the list) demonstrates this:
-
-\starttyping
-\startbuffer[demo]
-<doc>
- <pre><code>\ConTeXt\ is great</code></pre>
-
- <pre><code>but you need to know some tricks</code></pre>
-</doc>
-\stopbuffer
-
-\startxmlsetups xml:initialize
- \xmlsetsetup{#1}{doc|p|code}{xml:*}
- \xmlsetsetup{#1}{pre/code}{xml:pre:code}
-\stopxmlsetups
-
-\xmlregistersetup{xml:initialize}
-
-\startxmlsetups xml:doc
- \xmlflush{#1}
-\stopxmlsetups
-
-\startxmlsetups xml:pre:code
- no solution
- \comment[symbol=Key, location=inmargin,color=yellow]{\xmlflush{#1}}
- \par
- solution one \begingroup
- \expandUx
- \comment[symbol=Key, location=inmargin,color=yellow]{\xmlflush{#1}}
- \endgroup
- \par
- solution two
- \comment[symbol=Key, location=inmargin,color=yellow]{\xmlpure{#1}}
- \par
- \xmlprettyprint{#1}{tex}
-\stopxmlsetups
-
-\xmlprocessbuffer{main}{demo}{}
-\stoptyping
-
-The first comment (an interactive feature of \PDF\ comes out as:
-
-\starttyping
-\Ux {5C}ConTeXt\Ux {5C} is great
-\stoptyping
-
-The second and third comment are okay. It's one of the reasons why we have \type
-{\xmlpure}.
-
-\stopsection
-
-\stopchapter
-
+ \component xml-mkiv-converter
+ \component xml-mkiv-filtering
+ \component xml-mkiv-commands
+ \component xml-mkiv-expressions
+ \component xml-mkiv-tricks
+ \component xml-mkiv-lookups
+ \component xml-mkiv-examples
\stopbodymatter
\stoptext
diff --git a/metapost/context/base/mpiv/mp-blob.mpiv b/metapost/context/base/mpiv/mp-blob.mpiv
index d6773db21..318c78f4f 100644
--- a/metapost/context/base/mpiv/mp-blob.mpiv
+++ b/metapost/context/base/mpiv/mp-blob.mpiv
@@ -32,13 +32,13 @@ if mfun_use_one_pass :
vardef mfun_inject_blob(expr n) =
mfun_blob_c := nullpicture ;
- mfun_blob_b := lua.mp.blob_dimensions(mfun_blob_n,n) ;
+ mfun_blob_b := lua.mp.mf_blob_dimensions(mfun_blob_n,n) ;
addto mfun_blob_c doublepath unitsquare
xscaled redpart mfun_blob_b
yscaled (greenpart mfun_blob_b + bluepart mfun_blob_b)
shifted (0,- bluepart mfun_blob_b)
withprescript "mf_object=texblob"
- withprescript "tb_blob=" & decimal lua.mp.blob_index(mfun_blob_n,n) ;
+ withprescript "tb_blob=" & decimal lua.mp.mf_blob_index(mfun_blob_n,n) ;
mfun_blob_c
enddef ;
@@ -46,14 +46,14 @@ else :
vardef mfun_inject_blob(expr n) =
mfun_blob_c := nullpicture ;
- mfun_blob_b := lua.mp.blob_dimensions(mfun_blob_n,n) ;
+ mfun_blob_b := lua.mp.mf_blob_dimensions(mfun_blob_n,n) ;
addto mfun_blob_c doublepath unitsquare
xscaled redpart mfun_blob_b
yscaled (greenpart mfun_blob_b + bluepart mfun_blob_b)
shifted (0,- bluepart mfun_blob_b)
withprescript "mf_object=texblob"
withprescript "tb_stage=inject"
- withprescript "tb_blob=" & decimal lua.mp.blob_index(mfun_blob_n,n) ;
+ withprescript "tb_blob=" & decimal lua.mp.mf_blob_index(mfun_blob_n,n) ;
mfun_blob_c
enddef ;
@@ -71,19 +71,19 @@ if mfun_use_one_pass :
vardef followtext(expr pth, txt) =
image (
mfun_blob_n := mfun_blob_n + 1 ;
- lua.mp.InjectBlobB(mfun_blob_n,txt);
+ lua.mp.mf_inject_blob(mfun_blob_n,txt);
save pat, al, at, pl, pc, wid, pos, ap, ad, pic, len, n, sc ;
path pat ; pat := pth ;
numeric al, at, pl, pc, wid, pos, len[], n, sc ;
pair ap, ad ;
picture pic[] ;
len[0] := 0 ;
- n := lua.mp.blob_size(mfun_blob_n) ;
+ n := lua.mp.mf_blob_size(mfun_blob_n) ;
sc := 0 ;
for i=1 upto n :
pic[i] := mfun_inject_blob(i) ;
pic[i] := pic[i] shifted - llcorner pic[i] ;
- len[i] := len[i-1] + lua.mp.blob_width(mfun_blob_n,i) ;
+ len[i] := len[i-1] + lua.mp.mf_blob_width(mfun_blob_n,i) ;
endfor ;
al := arclength pth ;
if al = 0 :
@@ -107,7 +107,7 @@ if mfun_use_one_pass :
draw pat withpen pencircle scaled 1pt withcolor blue ;
fi ;
for i=1 upto n :
- wid := lua.mp.blob_width(mfun_blob_n,i) ;
+ wid := lua.mp.mf_blob_width(mfun_blob_n,i) ;
pos := len[i]-wid/2 + (i-1)*pl + pc ;
at := arctime pos of pat ;
ap := point at of pat ;
@@ -150,12 +150,12 @@ else :
pair ap, ad ;
picture pic[] ;
len[0] := 0 ;
- n := lua.mp.blob_size(mfun_blob_n) ;
+ n := lua.mp.mf_blob_size(mfun_blob_n) ;
sc := 0 ;
for i=1 upto n :
pic[i] := mfun_inject_blob(i) ;
pic[i] := pic[i] shifted - llcorner pic[i] ;
- len[i] := len[i-1] + lua.mp.blob_width(mfun_blob_n,i) ;
+ len[i] := len[i-1] + lua.mp.mf_blob_width(mfun_blob_n,i) ;
endfor ;
al := arclength pth ;
if al = 0 :
@@ -179,7 +179,7 @@ else :
draw pat withpen pencircle scaled 1pt withcolor blue ;
fi ;
for i=1 upto n :
- wid := lua.mp.blob_width(mfun_blob_n,i) ;
+ wid := lua.mp.mf_blob_width(mfun_blob_n,i) ;
pos := len[i]-wid/2 + (i-1)*pl + pc ;
at := arctime pos of pat ;
ap := point at of pat ;
diff --git a/metapost/context/base/mpiv/mp-grph.mpiv b/metapost/context/base/mpiv/mp-grph.mpiv
index a2f710881..2133d0ee5 100644
--- a/metapost/context/base/mpiv/mp-grph.mpiv
+++ b/metapost/context/base/mpiv/mp-grph.mpiv
@@ -139,7 +139,7 @@ if mfun_use_one_pass :
save figurepicture ; picture figurepicture ;
figurepicture := currentpicture ; currentpicture := nullpicture ;
currentgraphictext := currentgraphictext + 1 ;
- lua.mp.GraphicText(currentgraphictext,t) ;
+ lua.mp.mf_graphic_text(currentgraphictext,t) ;
mfun_finish_graphic_text % picks up directives
enddef ;
diff --git a/metapost/context/base/mpiv/mp-luas.mpiv b/metapost/context/base/mpiv/mp-luas.mpiv
index bebe4c0ad..d5aeec158 100644
--- a/metapost/context/base/mpiv/mp-luas.mpiv
+++ b/metapost/context/base/mpiv/mp-luas.mpiv
@@ -75,32 +75,69 @@ vardef mlib_luas_luacall(text t) =
)
enddef ;
+% vardef mlib_luas_lualist(expr c)(text t) =
+% save b ; boolean b ; b := false ;
+% runscript(c & "(" for s = t :
+% if b :
+% & ","
+% else :
+% hide(b := true)
+% fi
+% if string s :
+% % & ditto & s & ditto
+% & mfun_lua_bs & s & mfun_lua_es
+% elseif numeric s :
+% & decimal s
+% elseif boolean s :
+% & if s : "true" else : "false" fi
+% elseif pair s :
+% & mfun_pair_to_table(s)
+% elseif path s :
+% & mfun_path_to_table(s)
+% elseif rgbcolor s :
+% & mfun_rgb_to_table(s)
+% elseif cmykcolor s :
+% & mfun_cmyk_to_table(s)
+% else :
+% & ditto & tostring(s) & ditto
+% fi endfor & ")"
+% )
+% enddef ;
+
+newinternal mfun_luas_b ;
+
+def mlib_luas_luadone =
+ exitif numeric begingroup mfun_luas_b := 1 ; endgroup ;
+enddef ;
+
vardef mlib_luas_lualist(expr c)(text t) =
- save b ; boolean b ; b := false ;
- runscript(c & "(" for s = t :
- if b :
- & ","
+ interim mfun_luas_b := 0 ;
+ runscript(c & for s = t :
+ if mfun_luas_b = 0 :
+ "("
+ % hide(mfun_luas_b := 1)
+ mlib_luas_luadone
else :
- hide(b := true)
+ ","
fi
+ &
if string s :
- % & ditto & s & ditto
- & mfun_lua_bs & s & mfun_lua_es
+ mfun_lua_bs & s & mfun_lua_es
elseif numeric s :
- & decimal s
+ decimal s
elseif boolean s :
- & if s : "true" else : "false" fi
+ if s : "true" else : "false" fi
elseif pair s :
- & mfun_pair_to_table(s)
+ mfun_pair_to_table(s)
elseif path s :
- & mfun_path_to_table(s)
+ mfun_path_to_table(s)
elseif rgbcolor s :
- & mfun_rgb_to_table(s)
+ mfun_rgb_to_table(s)
elseif cmykcolor s :
- & mfun_cmyk_to_table(s)
+ mfun_cmyk_to_table(s)
else :
- & ditto & tostring(s) & ditto
- fi endfor & ")"
+ ditto & tostring(s) & ditto
+ fi & endfor if mfun_luas_b = 0 : "()" else : ")" fi
)
enddef ;
@@ -188,11 +225,11 @@ vardef texstr(expr name) = lua.mp.texstr(name) enddef ;
% \stopMPcode
def inpath suffix p =
- = 1 step 1 until lua.mp.mfun_path_length(str p)
+ = 1 step 1 until lua.mp.mf_path_length(str p)
enddef ;
-vardef pointof primary i = lua.mp.mfun_path_point(i) enddef ;
-vardef leftof primary i = lua.mp.mfun_path_left (i) enddef ;
-vardef rightof primary i = lua.mp.mfun_path_right(i) enddef ;
+vardef pointof primary i = lua.mp.mf_path_point(i) enddef ;
+vardef leftof primary i = lua.mp.mf_path_left (i) enddef ;
+vardef rightof primary i = lua.mp.mf_path_right(i) enddef ;
-extra_endfig := extra_endfig & " lua.mp.mfun_path_reset() ; " ;
+extra_endfig := extra_endfig & " lua.mp.mf_path_reset() ; " ;
diff --git a/metapost/context/base/mpiv/mp-mlib.mpiv b/metapost/context/base/mpiv/mp-mlib.mpiv
index 6fcc75d50..019020d82 100644
--- a/metapost/context/base/mpiv/mp-mlib.mpiv
+++ b/metapost/context/base/mpiv/mp-mlib.mpiv
@@ -202,7 +202,7 @@ if mfun_use_one_pass :
mfun_tt_c := nullpicture ;
mfun_tt_o := nullpicture ;
addto mfun_tt_o doublepath origin _op_ ; % save drawoptions
- mfun_tt_r := lua.mp.SomeText(mfun_tt_n,s) ;
+ mfun_tt_r := lua.mp.mf_some_text(mfun_tt_n,s) ;
addto mfun_tt_c doublepath unitsquare
xscaled redpart mfun_tt_r
yscaled (greenpart mfun_tt_r + bluepart mfun_tt_r)
@@ -220,7 +220,7 @@ if mfun_use_one_pass :
mfun_tt_c := nullpicture ;
mfun_tt_o := nullpicture ;
addto mfun_tt_o doublepath origin _op_ ; % save drawoptions
- mfun_tt_r := lua.mp.MadeText(mfun_tt_n) ;
+ mfun_tt_r := lua.mp.mf_made_text(mfun_tt_n) ;
addto mfun_tt_c doublepath unitsquare
xscaled redpart mfun_tt_r
yscaled (greenpart mfun_tt_r + bluepart mfun_tt_r)
@@ -255,7 +255,7 @@ else :
withprescript "tx_global=yes" ;
fi ;
else :
- mfun_tt_b := lua.mp.tt_dimensions(mfun_tt_n) ;
+ mfun_tt_b := lua.mp.mf_tt_dimensions(mfun_tt_n) ;
addto mfun_tt_c doublepath unitsquare
xscaled redpart mfun_tt_b
yscaled (greenpart mfun_tt_b + bluepart mfun_tt_b)
@@ -286,7 +286,7 @@ enddef ;
vardef rawtexbox(expr category, name) =
mfun_tt_c := nullpicture ;
if validtexbox(category,name) :
- mfun_tt_b := lua.mp.tb_dimensions(category, name) ;
+ mfun_tt_b := lua.mp.mf_tb_dimensions(category, name) ;
addto mfun_tt_c doublepath unitsquare
xscaled redpart mfun_tt_b
yscaled (greenpart mfun_tt_b + bluepart mfun_tt_b)
@@ -468,7 +468,7 @@ if mfun_use_one_pass :
mfun_tt_c := nullpicture ;
mfun_tt_o := nullpicture ;
addto mfun_tt_o doublepath origin _op_ ; % save drawoptions
- mfun_tt_r := lua.mp.SomeFormattedText(mfun_tt_n,t) ;
+ mfun_tt_r := lua.mp.mf_formatted_text(mfun_tt_n,t) ;
addto mfun_tt_c doublepath unitsquare
xscaled redpart mfun_tt_r
yscaled (greenpart mfun_tt_r + bluepart mfun_tt_r)
@@ -513,7 +513,7 @@ else :
withprescript "tx_global=yes" ;
fi ;
else :
- mfun_tt_b := lua.mp.tt_dimensions(mfun_tt_n) ;
+ mfun_tt_b := lua.mp.mf_tt_dimensions(mfun_tt_n) ;
addto mfun_tt_c doublepath unitsquare
xscaled redpart mfun_tt_b
yscaled (greenpart mfun_tt_b + bluepart mfun_tt_b)
@@ -1075,19 +1075,38 @@ def withmask primary filename =
withprescript "fg_mask=" & filename
enddef ;
-def externalfigure primary filename =
- if false :
- rawtextext("\externalfigure[" & filename & "]")
- else :
- image (
- addto currentpicture doublepath unitsquare
- withprescript "fg_name=" & filename ;
- )
-% unitsquare
-% withpen pencircle scaled 0
-% withprescript "fg_name=" & filename
- fi
-enddef ;
+if mfun_use_one_pass :
+
+ vardef externalfigure primary filename =
+ mfun_tt_c := nullpicture ;
+ mfun_tt_r := lua.mp.mf_external_figure(filename) ;
+ addto mfun_tt_c doublepath unitsquare
+ xscaled redpart mfun_tt_r
+ yscaled greenpart mfun_tt_r
+ withprescript "mf_object=figure"
+ withprescript "fg_name=" & filename ;
+ ;
+ mfun_tt_c
+ enddef ;
+
+else :
+
+ def externalfigure primary filename =
+ if false :
+ rawtextext("\externalfigure[" & filename & "]")
+ else :
+ image (
+ addto currentpicture doublepath unitsquare
+ withprescript "mf_object=figure"
+ withprescript "fg_name=" & filename ;
+ )
+ % unitsquare
+ % withpen pencircle scaled 0
+ % withprescript "fg_name=" & filename
+ fi
+ enddef ;
+
+fi ;
def figure primary filename =
rawtextext("\externalfigure[" & filename & "]")
@@ -1247,7 +1266,7 @@ if mfun_use_one_pass :
def mfun_do_outline_options_r = enddef ;
image ( normaldraw image (
% lua.mp.report("set outline text",currentoutlinetext);
- lua.mp.OutlineText(currentoutlinetext,t,kind) ;
+ lua.mp.mf_outline_text(currentoutlinetext,t,kind) ;
% lua.mp.report("get outline text",currentoutlinetext);
if kind = "f" :
mfun_do_outline_text_set_f rest ;
@@ -1264,7 +1283,7 @@ if mfun_use_one_pass :
else :
mfun_do_outline_text_set_n rest ;
fi ;
- lua.mp.get_outline_text(currentoutlinetext) ;
+ lua.mp.mf_get_outline_text(currentoutlinetext) ;
) mfun_do_outline_options_r ; )
enddef ;
@@ -1302,7 +1321,7 @@ else :
else :
mfun_do_outline_text_set_n rest ;
fi ;
- lua.mp.get_outline_text(currentoutlinetext) ;
+ lua.mp.mf_get_outline_text(currentoutlinetext) ;
fi ;
) mfun_do_outline_options_r ; )
enddef ;
@@ -1757,23 +1776,15 @@ def nofill text t = fill t withpostscript "collect" enddef ;
% so we can do: withcolor "red"
-% vardef resolvedcolor primary s =
-% % lua.mp.namedcolor(s) % conflicts with macro namedcolor
-% % lua.mp.NamedColor(s) % okay but, can also be
-% % lua.mp("NamedColor",s) % which gives expansion mess
-% if string s :
-% runscript("mp.NamedColor('" & s & "')") % faster anyway
-% else :
-% s
-% fi
-% enddef ;
+% We do a low level runscript:
+%
+% lua.mp.namedcolor(s) % conflicts with macro namedcolor
+% lua.mp.mf_named_color(s) % okay but, can also be
+% lua.mp("mf_named_color",s) % which gives expansion mess
def resolvedcolor primary s = % no vardef
- % lua.mp.namedcolor(s) % conflicts with macro namedcolor
- % lua.mp.NamedColor(s) % okay but, can also be
- % lua.mp("NamedColor",s) % which gives expansion mess
if string s :
- runscript("mp.NamedColor('" & s & "')") % faster anyway
+ runscript("mp.mf_named_color('" & s & "')") % faster anyway
else :
s
fi
diff --git a/metapost/context/base/mpiv/mp-page.mpiv b/metapost/context/base/mpiv/mp-page.mpiv
index 6e93bdaae..052bcbb23 100644
--- a/metapost/context/base/mpiv/mp-page.mpiv
+++ b/metapost/context/base/mpiv/mp-page.mpiv
@@ -188,6 +188,8 @@ fi ;
string CurrentLayout ; CurrentLayout := "default" ;
+% runscript("mp.PaperHeight()") % way faster of course
+
vardef PaperHeight = lua.mp.PaperHeight () enddef ;
vardef PaperWidth = lua.mp.PaperWidth () enddef ;
vardef PrintPaperHeight = lua.mp.PrintPaperHeight () enddef ;
diff --git a/metapost/context/base/mpiv/mp-tool.mpiv b/metapost/context/base/mpiv/mp-tool.mpiv
index 566f71056..281767522 100644
--- a/metapost/context/base/mpiv/mp-tool.mpiv
+++ b/metapost/context/base/mpiv/mp-tool.mpiv
@@ -244,19 +244,19 @@ boolean savingdata ; savingdata := false ;
boolean savingdatadone ; savingdatadone := false ;
def savedata expr txt =
- lua.mp.save_data(txt);
+ lua.mp.mf_save_data(txt);
enddef ;
def startsavingdata =
- lua.mp.start_saving_data();
+ lua.mp.mf_start_saving_data();
enddef ;
def stopsavingdata =
- lua.mp.stop_saving_data() ;
+ lua.mp.mf_stop_saving_data() ;
enddef ;
def finishsavingdata =
- lua.mp.finish_saving_data() ;
+ lua.mp.mf_finish_saving_data() ;
enddef ;
%D Instead of a keystroke eating save and allocation
diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii
index 7e089de90..a28121d0d 100644
--- a/tex/context/base/mkii/cont-new.mkii
+++ b/tex/context/base/mkii/cont-new.mkii
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\newcontextversion{2018.07.06 19:07}
+\newcontextversion{2018.07.10 15:52}
%D This file is loaded at runtime, thereby providing an
%D excellent place for hacks, patches, extensions and new
diff --git a/tex/context/base/mkii/context.mkii b/tex/context/base/mkii/context.mkii
index 09be8b091..6a88fbd1c 100644
--- a/tex/context/base/mkii/context.mkii
+++ b/tex/context/base/mkii/context.mkii
@@ -20,7 +20,7 @@
%D your styles an modules.
\edef\contextformat {\jobname}
-\edef\contextversion{2018.07.06 19:07}
+\edef\contextversion{2018.07.10 15:52}
%D For those who want to use this:
diff --git a/tex/context/base/mkii/mult-de.mkii b/tex/context/base/mkii/mult-de.mkii
index 2bd9353d0..6e30e12ad 100644
--- a/tex/context/base/mkii/mult-de.mkii
+++ b/tex/context/base/mkii/mult-de.mkii
@@ -1027,6 +1027,7 @@
\setinterfaceconstant{otherstext}{otherstext}
\setinterfaceconstant{outermargin}{outermargin}
\setinterfaceconstant{overprint}{overprint}
+\setinterfaceconstant{ownerpassword}{ownerpassword}
\setinterfaceconstant{ownnumber}{eigenenummer}
\setinterfaceconstant{page}{seite}
\setinterfaceconstant{pageboundaries}{seitenbegrenzung}
@@ -1268,6 +1269,7 @@
\setinterfaceconstant{up}{up}
\setinterfaceconstant{urlalternative}{urlalternative}
\setinterfaceconstant{urlspace}{urlspatium}
+\setinterfaceconstant{userpassword}{userpassword}
\setinterfaceconstant{validate}{validieren}
\setinterfaceconstant{values}{values}
\setinterfaceconstant{vcommand}{vbefehl}
diff --git a/tex/context/base/mkiv/attr-ini.mkiv b/tex/context/base/mkiv/attr-ini.mkiv
index e3d328e3d..3792b1c63 100644
--- a/tex/context/base/mkiv/attr-ini.mkiv
+++ b/tex/context/base/mkiv/attr-ini.mkiv
@@ -24,6 +24,7 @@
\installcorenamespace{attributecount} % the counter representing the attribute (attrdef'd)
\installcorenamespace{attributeid} % the internal number
\installcorenamespace{attributestack} % the attribute specific stack
+\installcorenamespace{attributepickup}
\unexpanded\def\pushattribute#1%
{\global\advance\csname\??attributestack\string#1\endcsname\plusone
@@ -40,12 +41,15 @@
\newtoks \t_attr_list_global
\newtoks \t_attr_list_local
+\newtoks \t_attr_list_pickup
\newtoks \t_attr_list_nomath
\ifdefined \s!global \else \def\s!global {global} \fi % for metatex % or hard check later
\ifdefined \s!public \else \def\s!public {public} \fi % for metatex % or hard check later
\ifdefined \s!private \else \def\s!private {private} \fi % for metatex % or hard check later
\ifdefined \s!attribute \else \def\s!attribute{attribute} \fi % for metatex % or hard check later
+\ifdefined \s!pickup \else \def\s!pickup {pickup} \fi % for metatex % or hard check later
+\ifdefined \s!forget \else \def\s!forget {forget} \fi % for metatex % or hard check later
\unexpanded\def\defineattribute {\dodoubleempty\attr_basics_define}
\unexpanded\def\definesystemattribute{\dodoubleempty\attr_basics_define_system}
@@ -53,6 +57,8 @@
\def\attr_basics_define {\attr_basics_define_indeed\s!public}
\def\attr_basics_define_system{\attr_basics_define_indeed\s!private}
+ % here public means 'visible' so it's not to be confused with 'public' at the lua end
+
\def\attr_basics_define_indeed#1[#2][#3]%
{\ifcsname\??attributecount#2\endcsname\else
\scratchcounter\clf_defineattribute{#2}{#1}\relax
@@ -66,11 +72,29 @@
{\etoksapp\t_attr_list_local {\csname\??attributecount#2\endcsname\attributeunsetvalue}}%
\doifinset\s!nomath{#3}%
{\etoksapp\t_attr_list_nomath{\csname\??attributecount#2\endcsname\attributeunsetvalue}}%
- % here public means 'visible' so it's not to be confused with 'public' at the lua end
\doifinset\s!public{#3}%
{\expandafter\let\csname#2\s!attribute\expandafter\endcsname\csname\??attributeid#2\endcsname}%
+ \doifinset\s!pickup{#3}%
+ {\expandafter\newconstant\csname\??attributepickup#2\endcsname
+ \csname\??attributepickup#2\endcsname\attributeunsetvalue
+ \etoksapp\t_attr_list_pickup{\csname\??attributecount#2\endcsname\csname\??attributepickup#2\endcsname}%
+ \ifcsname#2\s!attribute\endcsname
+ \expandafter\edef\csname\s!pickup#2\s!attribute\endcsname
+ {\csname\??attributepickup#2\endcsname\csname\??attributecount#2\endcsname}%
+ \expandafter\edef\csname\s!forget#2\s!attribute\endcsname
+ {\csname\??attributepickup#2\endcsname\attributeunsetvalue}%
+ \fi}%
\fi}
+\unexpanded\def\pickupattributes
+ {\the\t_attr_list_pickup\relax}
+
+% \unexpanded\def\pickupattribute#1%
+% {\csname\??attributecount#1\endcsname\csname\??attributepickup#1\endcsname}
+
+% \unexpanded\def\pickupattributelater#1%
+% {\csname\??attributepickup#1\endcsname\csname\??attributecount#1\endcsname}
+
\unexpanded\def\newattribute#1%
{\attr_basics_define_indeed\s!public[\csstring#1][]%
\expandafter\let\expandafter#1\csname\??attributeid\csstring#1\endcsname}
diff --git a/tex/context/base/mkiv/buff-ini.lua b/tex/context/base/mkiv/buff-ini.lua
index 970042c1b..632565fc7 100644
--- a/tex/context/base/mkiv/buff-ini.lua
+++ b/tex/context/base/mkiv/buff-ini.lua
@@ -182,7 +182,7 @@ local function collectcontent(name,separator) -- no print
end
local function loadcontent(name) -- no print
- local content = collectcontent(name,"\n") -- tex likes \n
+ local content = collectcontent(name,"\n") -- tex likes \n hm, elsewhere \r
local ok, err = load(content)
if ok then
return ok()
diff --git a/tex/context/base/mkiv/buff-ini.mkiv b/tex/context/base/mkiv/buff-ini.mkiv
index e487fc298..145f0f392 100644
--- a/tex/context/base/mkiv/buff-ini.mkiv
+++ b/tex/context/base/mkiv/buff-ini.mkiv
@@ -179,16 +179,16 @@
{\dosingleempty\buff_get}
\unexpanded\def\buff_get[#1]% [name]
- {\namedbufferparameter\empty\c!before
+ {\namedbufferparameter\empty\c!before\relax
\doifelsenothing{#1}
{\buff_get_stored_indeed\empty}
{\processcommalist[#1]\buff_get_stored_indeed}%
- \namedbufferparameter\empty\c!after}
+ \namedbufferparameter\empty\c!after\relax}
\unexpanded\def\buff_get_stored#1#2%
- {\namedbufferparameter{#1}\c!before
+ {\namedbufferparameter{#1}\c!before\relax
\buff_get_stored_indeed{#2}%
- \namedbufferparameter{#1}\c!after}
+ \namedbufferparameter{#1}\c!after\relax}
\unexpanded\def\buff_get_stored_indeed#1%
{\clf_getbuffer{#1}}
diff --git a/tex/context/base/mkiv/buff-ver.mkiv b/tex/context/base/mkiv/buff-ver.mkiv
index 47902ced7..7cf829b74 100644
--- a/tex/context/base/mkiv/buff-ver.mkiv
+++ b/tex/context/base/mkiv/buff-ver.mkiv
@@ -496,7 +496,7 @@
\def\buff_verbatim_typing_start_nop
{\typingparameter\c!before
- \startpacked[\v!blank]
+ \startpacked[\v!blank]%
\buff_verbatim_setup_line_numbering
\buff_verbatim_initialize_typing_one
\buff_verbatim_setup_keep_together
@@ -504,7 +504,7 @@
\def\buff_verbatim_typing_start_yes[#1]%
{\typingparameter\c!before
- \startpacked[\v!blank]
+ \startpacked[\v!blank]%
\doifelseassignment{#1}
{\setupcurrenttyping[#1]}
{\doif\v!continue{#1}{\lettypingparameter\c!continue\v!yes}}%
@@ -540,7 +540,7 @@
\dostoptagged
\endofverbatimlines
\dostoptagged
- \csname#2\endcsname}
+ \begincsname#2\endcsname}
\unexpanded\def\buff_verbatim_typing_stop#1% hm, currenttyping
{\stoppacked
diff --git a/tex/context/base/mkiv/cldf-ini.lua b/tex/context/base/mkiv/cldf-ini.lua
index dabdbb9b0..72f1276d2 100644
--- a/tex/context/base/mkiv/cldf-ini.lua
+++ b/tex/context/base/mkiv/cldf-ini.lua
@@ -1354,24 +1354,21 @@ do
local sentinel = string.char(26) -- ASCII SUB character : endoffileasciicode : ignorecatcode
local level = 0
- local function collect(c,...) -- can be optimized
- -- snippets
- for i=1,select("#",...) do
+ local function collect(c,a,...) -- can be optimized
+ if type(c) == "userdata" then
nofcollected = nofcollected + 1
- collected[nofcollected] = select(i,...)
+ -- collected[nofcollected] = userdata(c)
+ collected[nofcollected] = "\\" .. c.csname
+ end
+ if a then
+ for i=1,select("#",a,...) do
+ local c = select(i,a,...)
+ nofcollected = nofcollected + 1
+ collected[nofcollected] = type(c) == "userdata" and userdata(c) or c
+ end
end
end
- -- local function collectdirect(c,...) -- can be optimized
- -- -- lines
- -- for i=1,select("#",...) do
- -- n = n + 1
- -- t[n] = select(i,...)
- -- n = n + 1
- -- t[n] = "\r"
- -- end
- -- end
-
local collectdirect = collect
local permitted = true
diff --git a/tex/context/base/mkiv/cldf-ver.lua b/tex/context/base/mkiv/cldf-ver.lua
index 3710b2415..7a1c81301 100644
--- a/tex/context/base/mkiv/cldf-ver.lua
+++ b/tex/context/base/mkiv/cldf-ver.lua
@@ -13,32 +13,69 @@ if not modules then modules = { } end modules ['cldf-ver'] = {
local concat, tohandle = table.concat, table.tohandle
local splitlines, strip = string.splitlines, string.strip
local tostring, type = tostring, type
+local assignbuffer = buffers.assign
local context = context
-local function flush(...)
- context(concat{...,"\r"}) -- was \n
+context.tobuffer = assignbuffer -- (name,str,catcodes)
+
+function context.tolines(str,strip)
+ local lines = type(str) == "string" and splitlines(str) or str
+ for i=1,#lines do
+ if strip then
+ context(strip(lines[i]) .. " ")
+ else
+ context(lines[i] .. " ")
+ end
+ end
end
-local function t_tocontext(...)
- context.starttyping { "typing" } -- else [1] is intercepted
- context.pushcatcodes("verbatim")
- tohandle(flush,...) -- ok?
- context.stoptyping()
- context.popcatcodes()
+-- local function flush(...)
+-- context(concat { ..., "\r" }) -- was \n
+-- end
+--
+-- somehow this doesn't work any longer .. i need to figure out why
+--
+-- local function t_tocontext(t)
+-- context.starttyping { "typing" } -- else [1] is intercepted
+-- context.pushcatcodes("verbatim")
+-- -- tohandle(flush,...)
+-- context(table.serialize(t))
+-- context.stoptyping()
+-- context.popcatcodes()
+-- end
+--
+-- local function s_tocontext(first,second,...) -- we need to catch {\}
+-- context.type()
+-- context("{")
+-- context.pushcatcodes("verbatim")
+-- if second then
+-- context(concat({ first, second, ... }, " "))
+-- else
+-- context(first) -- no need to waste a { }
+-- end
+-- context.popcatcodes()
+-- context("}")
+-- end
+
+local t_buffer = { "t_o_c_o_n_t_e_x_t" }
+local t_typing = { "typing" }
+local t_type = { "type" }
+
+local function flush(s,inline)
+ assignbuffer("t_o_c_o_n_t_e_x_t",s)
+ context[inline and "typeinlinebuffer" or "typebuffer"](t_buffer)
+ context.resetbuffer(t_buffer)
end
-local function s_tocontext(first,...) -- we need to catch {\}
- context.type()
- context("{")
- context.pushcatcodes("verbatim")
- if first then
- context(first) -- no need to waste a { }
- else
- context(concat({first,...}," "))
- end
- context.popcatcodes()
- context("}")
+local function t_tocontext(t)
+ local s = table.serialize(t)
+ context(function() flush(s,false) end)
+end
+
+local function s_tocontext(first,second,...) -- we need to catch {\}
+ local s = second and concat({ first, second, ... }, " ") or first
+ context(function() flush(s,true) end)
end
local function b_tocontext(b)
@@ -74,15 +111,3 @@ end)
context.tocontext = tocontext
-context.tobuffer = buffers.assign -- (name,str,catcodes)
-
-function context.tolines(str,strip)
- local lines = type(str) == "string" and splitlines(str) or str
- for i=1,#lines do
- if strip then
- context(strip(lines[i]) .. " ")
- else
- context(lines[i] .. " ")
- end
- end
-end
diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv
index 277666af1..e2e0376c8 100644
--- a/tex/context/base/mkiv/cont-new.mkiv
+++ b/tex/context/base/mkiv/cont-new.mkiv
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\newcontextversion{2018.07.06 19:07}
+\newcontextversion{2018.07.10 15:52}
%D This file is loaded at runtime, thereby providing an excellent place for
%D hacks, patches, extensions and new features.
@@ -20,8 +20,22 @@
\writestatus\m!system{beware: some patches loaded from cont-new.mkiv}
+% math-ini.mkiv
+
\ifnum\texenginefunctionality<6753\else
\mathrulethicknessmode\zerocount
\fi
+% math-ini.mkiv
+
+\ifdefined\t \else \unexpanded\def\t{\mathortext\text\mathtext} \fi
+\ifdefined\w \else \unexpanded\def\w{\mathortext\word\mathword} \fi
+
+\appendtoks
+ \let\t\mathtext
+ \let\w\mathword
+\to \everymathematics
+
+% done
+
\protect \endinput
diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv
index 523af7cde..5407da02a 100644
--- a/tex/context/base/mkiv/context.mkiv
+++ b/tex/context/base/mkiv/context.mkiv
@@ -42,7 +42,7 @@
%D has to match \type {YYYY.MM.DD HH:MM} format.
\edef\contextformat {\jobname}
-\edef\contextversion{2018.07.06 19:07}
+\edef\contextversion{2018.07.10 15:52}
\edef\contextkind {beta}
%D For those who want to use this:
diff --git a/tex/context/base/mkiv/grph-inc.lua b/tex/context/base/mkiv/grph-inc.lua
index ce37c7c62..dd57c9dfa 100644
--- a/tex/context/base/mkiv/grph-inc.lua
+++ b/tex/context/base/mkiv/grph-inc.lua
@@ -1941,8 +1941,10 @@ function figures.getinfo(name,page)
end
if name.name then
local data = figures.push(name)
- figures.identify()
- figures.check()
+ data = figures.identify(data)
+ if data.status and data.status.status > 0 then
+ data = figures.check(data)
+ end
figures.pop()
return data
end
diff --git a/tex/context/base/mkiv/meta-blb.lua b/tex/context/base/mkiv/meta-blb.lua
index 639e22052..76e9e3362 100644
--- a/tex/context/base/mkiv/meta-blb.lua
+++ b/tex/context/base/mkiv/meta-blb.lua
@@ -87,20 +87,20 @@ local function blob_raw_wipe(i)
allblobs[i] = false
end
-mp.blob_raw_dimensions = blob_raw_dimensions
-mp.blob_raw_content = blob_raw_content
-mp.blob_raw_reset = blob_raw_reset
-mp.blob_raw_wipe = blob_raw_wipe
-mp.blob_raw_toutf = blob_raw_toutf
+mp.mf_blob_raw_dimensions = blob_raw_dimensions
+mp.mf_blob_raw_content = blob_raw_content
+mp.mf_blob_raw_reset = blob_raw_reset
+mp.mf_blob_raw_wipe = blob_raw_wipe
+mp.mf_blob_raw_toutf = blob_raw_toutf
-function mp.blob_new(category,text)
+function mp.mf_blob_new(category,text)
if trace then
report("category %a, text %a",category,text)
end
texblobs[category].text = text
end
-function mp.blob_add(category,blob)
+function mp.mf_blob_add(category,blob)
local tb = texblobs[category].blobs
local tn = #allblobs + 1
blob = hpack_nodes(blob)
@@ -111,7 +111,7 @@ function mp.blob_add(category,blob)
end
end
-function mp.blob_width(category,i)
+function mp.mf_blob_width(category,i)
local index = texblobs[category].blobs[i]
local blob = allblobs[index]
if blob then
@@ -121,15 +121,15 @@ function mp.blob_width(category,i)
end
end
-function mp.blob_size(category,i)
+function mp.mf_blob_size(category,i)
mpprint(#texblobs[category].blobs or 0)
end
-function mp.blob_index(category,i)
+function mp.mf_blob_index(category,i)
mpprint(texblobs[category].blobs[i] or 0)
end
-function mp.blob_dimensions(category,i)
+function mp.mf_blob_dimensions(category,i)
local index = texblobs[category].blobs[i]
local blob = allblobs[index]
if blob then
@@ -163,7 +163,7 @@ local function injectblob(object,blob)
end
end
-mp.blob_inject = injectblob
+-- mp.mf_blob_inject = injectblob
local function getblob(box,blob)
texsetbox(box,blob_raw_content(blob))
@@ -221,8 +221,8 @@ local flatten_list = node.flatten_discretionaries
local remove_node = nodes.remove
local flush_node = nodes.flush
-local addblob = mp.blob_add
-local newblob = mp.blob_new
+local addblob = mp.mf_blob_add
+local newblob = mp.mf_blob_new
local visible_code = {
[nodecodes.glyph] = true,
@@ -291,7 +291,7 @@ local ft_reset, ft_analyze, ft_process do
local mp_category = 0
local mp_str = ""
- function mp.InjectBlobB(category,str)
+ function mp.mf_inject_blob(category,str)
newblob(category,str) -- only for tracing
mp_category = category
mp_str = str
diff --git a/tex/context/base/mkiv/meta-ini.lua b/tex/context/base/mkiv/meta-ini.lua
index 6c4768671..f320efe20 100644
--- a/tex/context/base/mkiv/meta-ini.lua
+++ b/tex/context/base/mkiv/meta-ini.lua
@@ -117,23 +117,23 @@ do
local data = false
- function mp.start_saving_data(n)
+ function mp.mf_start_saving_data(n)
data = { }
end
- function mp.stop_saving_data()
+ function mp.mf_stop_saving_data()
if data then
-- nothing
end
end
- function mp.finish_saving_data()
+ function mp.mf_finish_saving_data()
if data then
-- nothing
end
end
- function mp.save_data(str)
+ function mp.mf_save_data(str)
if data then
data[#data+1] = str
end
diff --git a/tex/context/base/mkiv/meta-nod.lua b/tex/context/base/mkiv/meta-nod.lua
index 119c276e2..422b4ee14 100644
--- a/tex/context/base/mkiv/meta-nod.lua
+++ b/tex/context/base/mkiv/meta-nod.lua
@@ -6,24 +6,76 @@ if not modules then modules = { } end modules ['meta-nod'] = {
license = "see context related readme files"
}
+local tonumber = tonumber
+local P, R, Cs, lpegmatch = lpeg.P, lpeg.R, lpeg.Cs, lpeg.match
+
local references = { }
+local trace = false
+local report = logs.reporter("metapost","nodes")
-metapost.nodes = {
+local context = context
+local implement = interfaces.implement
- initialize = function()
- references = { }
- end,
+trackers.register("metapost.nodes", function(v) trace = v end)
- register = function(s,r)
- references[s] = r
- end,
+local word = R("AZ","az","__")^1
- resolve = function(s)
- context(references[s] or ("\\number " .. (tonumber(s) or 0)))
- end,
+local pattern = Cs (
+ (
+ word / function(s) return references[s] or s end
+ + P("{") / "["
+ + P("}") / "]"
+ + P(1)
+ )^1
+)
+
+implement {
+ name = "grph_nodes_initialize",
+ actions = function()
+ references = { }
+ end
+}
- reset = function()
+implement {
+ name = "grph_nodes_reset",
+ actions = function()
references = { }
- end,
+ end
+}
+
+implement {
+ name = "grph_nodes_register",
+ arguments = { "string", "integer" },
+ actions = function(s,r)
+ if not tonumber(s) then
+ if trace then
+ report("register %i as %a",t,s)
+ end
+ references[s] = r
+ end
+ end
+}
+implement {
+ name = "grph_nodes_resolve",
+ arguments = "string",
+ actions = function(s)
+ local r = references[s]
+ if r then
+ if trace then
+ report("resolve %a to %i",s,r)
+ end
+ context(r)
+ return
+ end
+ local n = lpegmatch(pattern,s)
+ if s ~= n then
+ if trace then
+ report("resolve '%s' to %s",s,n)
+ end
+ context(n)
+ return
+ end
+ context(s)
+ end
}
diff --git a/tex/context/base/mkiv/meta-nod.mkiv b/tex/context/base/mkiv/meta-nod.mkiv
index bf36e315c..9f966349c 100644
--- a/tex/context/base/mkiv/meta-nod.mkiv
+++ b/tex/context/base/mkiv/meta-nod.mkiv
@@ -110,6 +110,8 @@
%D Hm, we started out simple but it now quickly becomes the usual mess of
%D \TEX, \METAPOST\ and \LUA. Hard to understand.
+\newcount\c_meta_nodes_n
+
\unexpanded\def\startnodes
{\dosingleempty\meta_nodes_start}
@@ -121,11 +123,12 @@
\edef\p_meta_option{\metanodesparameter\c!option}%
\edef\p_meta_alternative{\metanodesparameter\c!alternative}%
\the\t_every_meta_nodes
+ \c_meta_nodes_n\zerocount
\t_meta_nodes\emptytoks
#2\removeunwantedspaces
% for alan, will be commented:
\writestatus{metanodes}{\detokenize\expandafter{\the\t_meta_nodes}}%
- \ctxlua{metapost.nodes.initialize()}%
+ \clf_grph_nodes_initialize
\startMPcode
mfun_node_init(%
\the\dimexpr\metanodesparameter\c!dx\relax,%
@@ -135,7 +138,7 @@
\the\t_meta_nodes ;
mfun_node_flush ;
\stopMPcode
- \ctxlua{metapost.nodes.reset()}%
+ \clf_grph_nodes_reset
\egroup}
\unexpanded\def\grph_nodes_node
@@ -149,10 +152,10 @@
\ifsecondargument
\setupcurrentmetanodes[#3]%
\fi
- \edef\p_label {#4}%
+ \edef\p_label{#4}%
\edef\p_reference{\metanodesparameter\c!reference}%
\ifx\p_reference\empty\else
- \ctxlua{metapost.nodes.register("\p_reference",\number#1)}%
+ \clf_grph_nodes_register{\p_reference}\c_meta_nodes_n\relax
\fi
\normalexpanded{\endgroup\noexpand\etoksapp\t_meta_nodes{%
mfun_node_make(\number#1,\number#2%
@@ -162,7 +165,8 @@
,"\metanodesparameter\c!command{\p_label}"%
\fi
);%
- }}}
+ }}%
+ \advance\c_meta_nodes_n\plusone}
\appendtoks
\let\placenode\grph_nodes_node
@@ -210,7 +214,7 @@
mfun_nodes_fromto\begincsname\??metanodesposition\metanodesparameter\c!position\endcsname(%
\metanodesparameter\c!offset,%
% \number#1,\number#2%
- \ctxlua{metapost.nodes.resolve("#1")},\ctxlua{metapost.nodes.resolve("#2")}%
+ \clf_grph_nodes_resolve{#1},\clf_grph_nodes_resolve{#2}%
\ifx\p_label\empty
,""%
\else
diff --git a/tex/context/base/mkiv/mlib-lua.lua b/tex/context/base/mkiv/mlib-lua.lua
index 5d0ab1ab6..785d3c947 100644
--- a/tex/context/base/mkiv/mlib-lua.lua
+++ b/tex/context/base/mkiv/mlib-lua.lua
@@ -28,121 +28,16 @@ local trace_enabled = true
local be_tolerant = true directives.register("metapost.lua.tolerant", function(v) be_tolerant = v end)
-mp = mp or { } -- system namespace
-MP = MP or { } -- user namespace
+local get, set, aux = { }, { }, { }
-local buffer = { }
-local n = 0
-local max = 20 -- we reuse upto max
-local nesting = 0
-
-function mp._f_()
- if trace_enabled and trace_luarun then
- local result = concat(buffer," ",1,n)
- if n > max then
- buffer = { }
- end
- n = 0
- report_luarun("%i: data: %s",nesting,result)
- return result
- else
- if n == 0 then
- return ""
- end
- local result
- if n == 1 then
- result = buffer[1]
- else
- result = concat(buffer," ",1,n)
- end
- if n > max then
- buffer = { }
- end
- n = 0
- return result
- end
-end
-
-local f_code = formatters["%s return mp._f_()"]
-
-local f_integer = formatters["%i"]
-
--- local f_numeric = formatters["%.16f"]
--- local f_pair = formatters["(%.16f,%.16f)"]
--- local f_triplet = formatters["(%.16f,%.16f,%.16f)"]
--- local f_quadruple = formatters["(%.16f,%.16f,%.16f,%.16f)"]
-
-local f_numeric = formatters["%n"]
-local f_pair = formatters["(%n,%n)"]
-local f_ctrl = formatters["(%n,%n) .. controls (%n,%n) and (%n,%n)"]
-local f_triplet = formatters["(%n,%n,%n)"]
-local f_quadruple = formatters["(%n,%n,%n,%n)"]
-
-local f_points = formatters["%p"]
-local f_pair_pt = formatters["(%p,%p)"]
-local f_ctrl_pt = formatters["(%p,%p) .. controls (%p,%p) and (%p,%p)"]
-local f_triplet_pt = formatters["(%p,%p,%p)"]
-local f_quadruple_pt = formatters["(%p,%p,%p,%p)"]
-
-local function mpprint(...) -- we can optimize for n=1
- for i=1,select("#",...) do
- local value = select(i,...)
- if value ~= nil then
- n = n + 1
- local t = type(value)
- if t == "number" then
- buffer[n] = f_numeric(value)
- elseif t == "string" then
- buffer[n] = value
- elseif t == "table" then
- buffer[n] = "(" .. concat(value,",") .. ")"
- else -- boolean or whatever
- buffer[n] = tostring(value)
- end
- end
- end
-end
-
-local r = P('%') / "percent"
- + P('"') / "dquote"
- + P('\n') / "crlf"
- -- + P(' ') / "space"
-local a = Cc("&")
-local q = Cc('"')
-local p = Cs(q * (r * a)^-1 * (a * r * (P(-1) + a) + P(1))^0 * q)
-
-local function mpvprint(...) -- variable print
- for i=1,select("#",...) do
- local value = select(i,...)
- if value ~= nil then
- n = n + 1
- local t = type(value)
- if t == "number" then
- buffer[n] = f_numeric(value)
- elseif t == "string" then
- buffer[n] = lpegmatch(p,value)
- elseif t == "table" then
- local m = #t
- if m == 2 then
- buffer[n] = f_pair(unpack(t))
- elseif m == 3 then
- buffer[n] = f_triplet(unpack(t))
- elseif m == 4 then
- buffer[n] = f_quadruple(unpack(t))
- else -- error
- buffer[n] = ""
- end
- else -- boolean or whatever
- buffer[n] = tostring(value)
- end
- end
- end
-end
-
-mp.cleaned = function(s) return lpegmatch(p,s) or s end
+mp = mp or { -- system namespace
+ set = set,
+ get = get,
+ aux = aux,
+}
-mp.print = mpprint
-mp.vprint = mpvprint
+MP = MP or { -- user namespace
+}
-- We had this:
--
@@ -157,238 +52,486 @@ mp.vprint = mpvprint
-- lua.mp("somedefdname","foo")
table.setmetatablecall(mp,function(t,k,...) return t[k](...) end)
+table.setmetatablecall(MP,function(t,k,...) return t[k](...) end)
-function mp.boolean(b)
- n = n + 1
- buffer[n] = b and "true" or "false"
-end
-
-function mp.numeric(f)
- n = n + 1
- buffer[n] = f and f_numeric(f) or "0"
-end
+do
-function mp.integer(i)
- n = n + 1
- -- buffer[n] = i and f_integer(i) or "0"
- buffer[n] = i or "0"
-end
+ local currentmpx = nil
+ local stack = { }
-function mp.points(i)
- n = n + 1
- buffer[n] = i and f_points(i) or "0pt"
-end
+ local get_numeric = mplib.get_numeric
+ local get_string = mplib.get_string
+ local get_boolean = mplib.get_boolean
+ local get_path = mplib.get_path
+ local set_path = mplib.set_path
-function mp.pair(x,y)
- n = n + 1
- if type(x) == "table" then
- buffer[n] = f_pair(x[1],x[2])
- else
- buffer[n] = f_pair(x,y)
- end
-end
+ get.numeric = function(s) return get_numeric(currentmpx,s) end
+ get.string = function(s) return get_string (currentmpx,s) end
+ get.boolean = function(s) return get_boolean(currentmpx,s) end
+ get.path = function(s) return get_path (currentmpx,s) end
+ get.number = function(s) return get_numeric(currentmpx,s) end
-function mp.pairpoints(x,y)
- n = n + 1
- if type(x) == "table" then
- buffer[n] = f_pair_pt(x[1],x[2])
- else
- buffer[n] = f_pair_pt(x,y)
- end
-end
+ set.path = function(s,t) return set_path(currentmpx,s,t) end -- not working yet
-function mp.triplet(x,y,z)
- n = n + 1
- if type(x) == "table" then
- buffer[n] = f_triplet(x[1],x[2],x[3])
- else
- buffer[n] = f_triplet(x,y,z)
+ function metapost.pushscriptrunner(mpx)
+ insert(stack,mpx)
+ currentmpx = mpx
end
-end
-function mp.tripletpoints(x,y,z)
- n = n + 1
- if type(x) == "table" then
- buffer[n] = f_triplet_pt(x[1],x[2],x[3])
- else
- buffer[n] = f_triplet_pt(x,y,z)
+ function metapost.popscriptrunner()
+ currentmpx = remove(stack,mpx)
end
-end
-function mp.quadruple(w,x,y,z)
- n = n + 1
- if type(w) == "table" then
- buffer[n] = f_quadruple(w[1],w[2],w[3],w[4])
- else
- buffer[n] = f_quadruple(w,x,y,z)
- end
end
-function mp.quadruplepoints(w,x,y,z)
- n = n + 1
- if type(w) == "table" then
- buffer[n] = f_quadruple_pt(w[1],w[2],w[3],w[4])
- else
- buffer[n] = f_quadruple_pt(w,x,y,z)
- end
-end
+do
-local function mppath(f2,f6,t,connector,cycle)
- if type(t) == "table" then
- local tn = #t
- if tn > 0 then
- if connector == true then
- connector = "--"
- cycle = true
- elseif not connector then
- connector = "--"
+ local buffer = { }
+ local n = 0
+ local max = 20 -- we reuse upto max
+ local nesting = 0
+ local runs = 0
+
+ local function _f_()
+ if trace_enabled and trace_luarun then
+ local result = concat(buffer," ",1,n)
+ if n > max then
+ buffer = { }
end
- local ti = t[1]
- n = n + 1 ;
- if #ti == 6 then
- local tn = t[2] or t[1]
- buffer[n] = f6(ti[1],ti[2],ti[5],ti[6],tn[3],tn[4])
+ n = 0
+ report_luarun("%i: data: %s",nesting,result)
+ return result
+ else
+ if n == 0 then
+ return ""
+ end
+ local result
+ if n == 1 then
+ result = buffer[1]
else
- buffer[n] = f2(ti[1],ti[2])
+ result = concat(buffer," ",1,n)
end
- for i=2,tn do
- local ti = t[i]
- n = n + 1 ; buffer[n] = connector
- n = n + 1 ;
- if #ti == 6 and (i < tn or cycle) then
- local tn = t[i+1] or t[1]
- buffer[n] = f6(ti[1],ti[2],ti[5],ti[6],tn[3],tn[4])
- else
- buffer[n] = f2(ti[1],ti[2])
+ if n > max then
+ buffer = { }
+ end
+ n = 0
+ return result
+ end
+ end
+
+ mp._f_ = _f_ -- convenient to have it in a top module
+ aux.flush = _f_
+
+ local f_code = formatters["%s return mp._f_()"]
+
+ local f_integer = formatters["%i"]
+ -- local f_numeric = formatters["%.16f"]
+ -- local f_pair = formatters["(%.16f,%.16f)"]
+ -- local f_triplet = formatters["(%.16f,%.16f,%.16f)"]
+ -- local f_quadruple = formatters["(%.16f,%.16f,%.16f,%.16f)"]
+
+ -- %N
+
+ local f_numeric = formatters["%n"]
+ local f_pair = formatters["(%n,%n)"]
+ local f_ctrl = formatters["(%n,%n) .. controls (%n,%n) and (%n,%n)"]
+ local f_triplet = formatters["(%n,%n,%n)"]
+ local f_quadruple = formatters["(%n,%n,%n,%n)"]
+
+ local f_points = formatters["%p"]
+ local f_pair_pt = formatters["(%p,%p)"]
+ local f_ctrl_pt = formatters["(%p,%p) .. controls (%p,%p) and (%p,%p)"]
+ local f_triplet_pt = formatters["(%p,%p,%p)"]
+ local f_quadruple_pt = formatters["(%p,%p,%p,%p)"]
+
+ local r = P('%') / "percent"
+ + P('"') / "dquote"
+ + P('\n') / "crlf"
+ -- + P(' ') / "space"
+ local a = Cc("&")
+ local q = Cc('"')
+ local p = Cs(q * (r * a)^-1 * (a * r * (P(-1) + a) + P(1))^0 * q)
+
+ mp.cleaned = function(s) return lpegmatch(p,s) or s end
+
+ local function mpprint(...) -- we can optimize for n=1
+ for i=1,select("#",...) do
+ local value = select(i,...)
+ if value ~= nil then
+ n = n + 1
+ local t = type(value)
+ if t == "number" then
+ buffer[n] = f_numeric(value)
+ elseif t == "string" then
+ buffer[n] = value
+ elseif t == "table" then
+ buffer[n] = "(" .. concat(value,",") .. ")"
+ else -- boolean or whatever
+ buffer[n] = tostring(value)
end
end
- if cycle then
- n = n + 1 ; buffer[n] = connector
- n = n + 1 ; buffer[n] = "cycle"
+ end
+ end
+
+ local function mpvprint(...) -- variable print
+ for i=1,select("#",...) do
+ local value = select(i,...)
+ if value ~= nil then
+ n = n + 1
+ local t = type(value)
+ if t == "number" then
+ buffer[n] = f_numeric(value)
+ elseif t == "string" then
+ buffer[n] = lpegmatch(p,value)
+ elseif t == "table" then
+ local m = #t
+ if m == 2 then
+ buffer[n] = f_pair(unpack(t))
+ elseif m == 3 then
+ buffer[n] = f_triplet(unpack(t))
+ elseif m == 4 then
+ buffer[n] = f_quadruple(unpack(t))
+ else -- error
+ buffer[n] = ""
+ end
+ else -- boolean or whatever
+ buffer[n] = tostring(value)
+ end
end
end
end
-end
-function mp.path(...)
- mppath(f_pair,f_ctrl,...)
-end
+ local function mpboolean(b)
+ n = n + 1
+ buffer[n] = b and "true" or "false"
+ end
-function mp.pathpoints(...)
- mppath(f_pair_pt,f_ctrl_pt,...)
-end
+ local function mpnumeric(f)
+ n = n + 1
+ buffer[n] = f and f_numeric(f) or "0"
+ end
+ local function mpinteger(i)
+ n = n + 1
+ -- buffer[n] = i and f_integer(i) or "0"
+ buffer[n] = i or "0"
+ end
-function mp.pathpoints(t,connector,cycle)
- if type(t) == "table" then
- local tn = #t
- if tn > 0 then
- if connector == true then
- connector = "--"
- cycle = true
- elseif not connector then
- connector = "--"
- end
- local ti = t[1]
- n = n + 1 ;
- if #ti == 6 then
- buffer[n] = f_pair_pt_ctrl(ti[1],ti[2],ti[3],ti[4],ti[5],ti[6])
- else
- buffer[n] = f_pair_pt(ti[1],ti[2])
- end
- for i=2,tn do
- local ti = t[i]
- n = n + 1 ; buffer[n] = connector
+ local function mppoints(i)
+ n = n + 1
+ buffer[n] = i and f_points(i) or "0pt"
+ end
+
+ local function mppair(x,y)
+ n = n + 1
+ if type(x) == "table" then
+ buffer[n] = f_pair(x[1],x[2])
+ else
+ buffer[n] = f_pair(x,y)
+ end
+ end
+
+ local function mppairpoints(x,y)
+ n = n + 1
+ if type(x) == "table" then
+ buffer[n] = f_pair_pt(x[1],x[2])
+ else
+ buffer[n] = f_pair_pt(x,y)
+ end
+ end
+
+ local function mptriplet(x,y,z)
+ n = n + 1
+ if type(x) == "table" then
+ buffer[n] = f_triplet(x[1],x[2],x[3])
+ else
+ buffer[n] = f_triplet(x,y,z)
+ end
+ end
+
+ local function mptripletpoints(x,y,z)
+ n = n + 1
+ if type(x) == "table" then
+ buffer[n] = f_triplet_pt(x[1],x[2],x[3])
+ else
+ buffer[n] = f_triplet_pt(x,y,z)
+ end
+ end
+
+ local function mpquadruple(w,x,y,z)
+ n = n + 1
+ if type(w) == "table" then
+ buffer[n] = f_quadruple(w[1],w[2],w[3],w[4])
+ else
+ buffer[n] = f_quadruple(w,x,y,z)
+ end
+ end
+
+ local function mpquadruplepoints(w,x,y,z)
+ n = n + 1
+ if type(w) == "table" then
+ buffer[n] = f_quadruple_pt(w[1],w[2],w[3],w[4])
+ else
+ buffer[n] = f_quadruple_pt(w,x,y,z)
+ end
+ end
+
+ -- local function mp_path(f2,f6,t,connector,cycle)
+ -- if type(t) == "table" then
+ -- local tn = #t
+ -- if tn > 0 then
+ -- if connector == true then
+ -- connector = "--"
+ -- cycle = true
+ -- elseif not connector then
+ -- connector = "--"
+ -- end
+ -- local ti = t[1]
+ -- n = n + 1 ;
+ -- if #ti == 6 then
+ -- local tn = t[2] or t[1]
+ -- buffer[n] = f6(ti[1],ti[2],ti[5],ti[6],tn[3],tn[4])
+ -- else
+ -- buffer[n] = f2(ti[1],ti[2])
+ -- end
+ -- for i=2,tn do
+ -- local ti = t[i]
+ -- n = n + 1 ; buffer[n] = connector
+ -- n = n + 1 ;
+ -- if #ti == 6 and (i < tn or cycle) then
+ -- local tn = t[i+1] or t[1]
+ -- buffer[n] = f6(ti[1],ti[2],ti[5],ti[6],tn[3],tn[4])
+ -- else
+ -- buffer[n] = f2(ti[1],ti[2])
+ -- end
+ -- end
+ -- if cycle then
+ -- n = n + 1 ; buffer[n] = connector
+ -- n = n + 1 ; buffer[n] = "cycle"
+ -- end
+ -- end
+ -- end
+ -- end
+
+ local function mp_path(f2,f6,t,connector,cycle)
+ if type(t) == "table" then
+ local tn = #t
+ if tn > 0 then
+ if connector == true then
+ connector = "--"
+ cycle = true
+ elseif not connector then
+ connector = "--"
+ end
+ local ti = t[1]
n = n + 1 ;
if #ti == 6 then
- buffer[n] = f_pair_pt_ctrl(ti[1],ti[2],ti[3],ti[4],ti[5],ti[6])
+ buffer[n] = f6(ti[1],ti[2],ti[3],ti[4],ti[5],ti[6])
else
- buffer[n] = f_pair_pt(ti[1],ti[2])
+ buffer[n] = f2(ti[1],ti[2])
+ end
+ for i=2,tn do
+ local ti = t[i]
+ n = n + 1 ; buffer[n] = connector
+ n = n + 1 ;
+ if #ti == 6 then
+ buffer[n] = f6(ti[1],ti[2],ti[3],ti[4],ti[5],ti[6])
+ else
+ buffer[n] = f2(ti[1],ti[2])
+ end
+ end
+ if cycle then
+ n = n + 1 ; buffer[n] = connector
+ n = n + 1 ; buffer[n] = "cycle"
end
- end
- if cycle then
- n = n + 1 ; buffer[n] = connector
- n = n + 1 ; buffer[n] = "cycle"
end
end
end
-end
-function mp.size(t)
- n = n + 1
- buffer[n] = type(t) == "table" and f_numeric(#t) or "0"
-end
+ local function mppath(...)
+ mp_path(f_pair,f_pair_ctrl,...)
+ end
-local mpnamedcolor = attributes.colors.mpnamedcolor
+ local function mppathpoints(...)
+ mp_path(f_pair_pt,f_pair_pt_ctrl,...)
+ end
-mp.NamedColor = function(str)
- mpprint(mpnamedcolor(str))
-end
+ local function mpsize(t)
+ n = n + 1
+ buffer[n] = type(t) == "table" and f_numeric(#t) or "0"
+ end
--- experiment: names can change
+ local replacer = lpeg.replacer("@","%%")
+
+ local function mpfprint(fmt,...)
+ n = n + 1
+ if not find(fmt,"%",1,true) then
+ fmt = lpegmatch(replacer,fmt)
+ end
+ buffer[n] = formatters[fmt](...)
+ end
-local datasets = { }
-mp.datasets = datasets
+ local function mpquoted(fmt,s,...)
+ n = n + 1
+ if s then
+ if not find(fmt,"%",1,true) then
+ fmt = lpegmatch(replacer,fmt)
+ end
+ -- buffer[n] = '"' .. formatters[fmt](s,...) .. '"'
+ buffer[n] = lpegmatch(p,formatters[fmt](s,...))
+ elseif fmt then
+ -- buffer[n] = '"' .. fmt .. '"'
+ buffer[n] = lpegmatch(p,fmt)
+ else
+ -- something is wrong
+ end
+ end
-function datasets.load(tag,filename)
- if not filename then
- tag, filename = file.basename(tag), tag
+ aux.print = mpprint
+ aux.vprint = mpvprint
+ aux.boolean = mpboolean
+ aux.numeric = mpnumeric
+ aux.number = mpnumeric
+ aux.integer = mpinteger
+ aux.points = mppoints
+ aux.pair = mppair
+ aux.pairpoints = mppairpoints
+ aux.triplet = mptriplet
+ aux.tripletpoints = mptripletpoints
+ aux.quadruple = mpquadruple
+ aux.quadruplepoints = mpquadruplepoints
+ aux.path = mppath
+ aux.pathpoints = mppathpoints
+ aux.size = mpsize
+ aux.fprint = mpfprint
+ aux.quoted = mpquoted
+
+ -- we need access to the variables
+
+ function metapost.nofscriptruns()
+ return runs
+ end
+
+ -- there is no gain in:
+ --
+ -- local cache = table.makeweak()
+ --
+ -- f = cache[code]
+ -- if not f then
+ -- f = loadstring(f_code(code))
+ -- if f then
+ -- cache[code] = f
+ -- elseif be_tolerant then
+ -- f = loadstring(code)
+ -- if f then
+ -- cache[code] = f
+ -- end
+ -- end
+ -- end
+
+ function metapost.runscript(code)
+ nesting = nesting + 1
+ local trace = trace_enabled and trace_luarun
+ if trace then
+ report_luarun("%i: code: %s",nesting,code)
+ end
+ runs = runs + 1
+ local f = loadstring(f_code(code))
+ if not f and be_tolerant then
+ f = loadstring(code)
+ end
+ if f then
+ local _buffer_, _n_ = buffer, n
+ buffer, n = { }, 0
+ local result = f()
+ if result then
+ local t = type(result)
+ if t == "number" then
+ result = f_numeric(result)
+ elseif t ~= "string" then
+ result = tostring(result)
+ end
+ if trace then
+ if #result == 0 then
+ report_luarun("%i: no result",nesting)
+-- print(debug.traceback())
+ else
+ report_luarun("%i: result: %s",nesting,result)
+ end
+ end
+ buffer, n = _buffer_, _n_
+ nesting = nesting - 1
+ return result
+ elseif trace then
+ report_luarun("%i: no result",nesting)
+-- print(debug.traceback())
+ end
+ buffer, n = _buffer_, _n_
+ else
+ report_luarun("%i: no result, invalid code: %s",nesting,code)
+ end
+ nesting = nesting - 1
+ return ""
end
- local data = mp.dataset(io.loaddata(filename) or "")
- datasets[tag] = {
- Data = data,
- Line = function(n) mp.path(data[n or 1]) end,
- Size = function() mp.size(data) end,
- }
-end
---
+ -- for the moment
-local replacer = lpeg.replacer("@","%%")
+ for k, v in next, aux do mp[k] = v end
-function mp.fprint(fmt,...)
- n = n + 1
- if not find(fmt,"%",1,true) then
- fmt = lpegmatch(replacer,fmt)
- end
- buffer[n] = formatters[fmt](...)
end
-local function mpquoted(fmt,s,...)
- n = n + 1
- if s then
- if not find(fmt,"%",1,true) then
- fmt = lpegmatch(replacer,fmt)
- end
- -- buffer[n] = '"' .. formatters[fmt](s,...) .. '"'
- buffer[n] = lpegmatch(p,formatters[fmt](s,...))
- elseif fmt then
- -- buffer[n] = '"' .. fmt .. '"'
- buffer[n] = lpegmatch(p,fmt)
- else
- -- something is wrong
+do
+
+ local mpnamedcolor = attributes.colors.mpnamedcolor
+ local mpprint = aux.print
+
+ mp.mf_named_color = function(str)
+ mpprint(mpnamedcolor(str))
end
-end
-mp.quoted = mpquoted
+end
-function mp.n(t)
+function mp.n(t) -- used ?
return type(t) == "table" and #t or 0
end
-local whitespace = lpegpatterns.whitespace
-local newline = lpegpatterns.newline
-local setsep = newline^2
-local comment = (S("#%") + P("--")) * (1-newline)^0 * (whitespace - setsep)^0
-local value = (1-whitespace)^1 / tonumber
-local entry = Ct( value * whitespace * value)
-local set = Ct((entry * (whitespace-setsep)^0 * comment^0)^1)
-local series = Ct((set * whitespace^0)^1)
+do
+
+ -- experiment: names can change
+
+ local mppath = aux.mppath
+ local mpsize = aux.mpsize
-local pattern = whitespace^0 * series
+ local whitespace = lpegpatterns.whitespace
+ local newline = lpegpatterns.newline
+ local setsep = newline^2
+ local comment = (S("#%") + P("--")) * (1-newline)^0 * (whitespace - setsep)^0
+ local value = (1-whitespace)^1 / tonumber
+ local entry = Ct( value * whitespace * value)
+ local set = Ct((entry * (whitespace-setsep)^0 * comment^0)^1)
+ local series = Ct((set * whitespace^0)^1)
+
+ local pattern = whitespace^0 * series
+
+ local datasets = { }
+ mp.datasets = datasets
+
+ function mp.dataset(str)
+ return lpegmatch(pattern,str)
+ end
+
+ function datasets.load(tag,filename)
+ if not filename then
+ tag, filename = file.basename(tag), tag
+ end
+ local data = lpegmatch(pattern,io.loaddata(filename) or "")
+ datasets[tag] = {
+ Data = data,
+ Line = function(n) mppath(data[n or 1]) end,
+ Size = function() mpsize(data) end,
+ }
+ end
-function mp.dataset(str)
- return lpegmatch(pattern,str)
end
-- \startluacode
@@ -420,269 +563,183 @@ end
-- endfor ;
-- \stopMPpage
-local runs = 0
-
-function metapost.nofscriptruns()
- return runs
-end
-
--- there is no gain in:
---
--- local cache = table.makeweak()
---
--- f = cache[code]
--- if not f then
--- f = loadstring(f_code(code))
--- if f then
--- cache[code] = f
--- elseif be_tolerant then
--- f = loadstring(code)
--- if f then
--- cache[code] = f
--- end
--- end
--- end
-
-function metapost.runscript(code)
- nesting = nesting + 1
- local trace = trace_enabled and trace_luarun
- if trace then
- report_luarun("%i: code: %s",nesting,code)
- end
- runs = runs + 1
- local f = loadstring(f_code(code))
- if not f and be_tolerant then
- f = loadstring(code)
- end
- if f then
- local _buffer_, _n_ = buffer, n
- buffer, n = { }, 0
- local result = f()
- if result then
- local t = type(result)
- if t == "number" then
- result = f_numeric(result)
- elseif t ~= "string" then
- result = tostring(result)
- end
- if trace then
- if #result == 0 then
- report_luarun("%i: no result",nesting)
- else
- report_luarun("%i: result: %s",nesting,result)
- end
- end
- buffer, n = _buffer_, _n_
- nesting = nesting - 1
- return result
- elseif trace then
- report_luarun("%i: no result",nesting)
- end
- buffer, n = _buffer_, _n_
- else
- report_luarun("%i: no result, invalid code: %s",nesting,code)
- end
- nesting = nesting - 1
- return ""
-end
+-- texts:
do
- local get_numeric = mplib.get_numeric
- local get_string = mplib.get_string
- local get_boolean = mplib.get_boolean
- local get_path = mplib.get_path
- local get_number = get_numeric
+ local mptriplet = mp.triplet
- local set_path = mplib.set_path
+ local bpfactor = number.dimenfactors.bp
+ local textexts = nil
+ local mptriplet = mp.triplet
+ local nbdimensions = nodes.boxes.dimensions
- local currentmpx = nil
- local stack = { }
- local getters = { }
- local setters = { }
-
- getters.numeric = function(s) return get_numeric(currentmpx,s) end
- getters.string = function(s) return get_string (currentmpx,s) end
- getters.boolean = function(s) return get_boolean(currentmpx,s) end
- getters.path = function(s) return get_path (currentmpx,s) end
- getters.number = mp.numeric
-
- setters.path = function(s,t) return set_path(currentmpx,s,t) end
+ function mp.mf_tt_initialize(tt)
+ textexts = tt
+ end
- function metapost.pushscriptrunner(mpx)
- insert(stack,mpx)
- currentmpx = mpx
+ function mp.mf_tt_dimensions(n)
+ local box = textexts and textexts[n]
+ if box then
+ -- could be made faster with nuts but not critical
+ mptriplet(box.width*bpfactor,box.height*bpfactor,box.depth*bpfactor)
+ else
+ mptriplet(0,0,0)
+ end
end
- function metapost.popscriptrunner()
- currentmpx = remove(stack,mpx)
+ function mp.mf_tb_dimensions(category,name)
+ local w, h, d = nbdimensions(category,name)
+ mptriplet(w*bpfactor,h*bpfactor,d*bpfactor)
end
- mp.get = getters
- mp.set = setters
+ function mp.report(a,b)
+ if b then
+ report_message("%s : %s",a,b)
+ elseif a then
+ report_message("%s : %s","message",a)
+ end
+ end
end
--- texts:
+do
-local factor = 65536*(7227/7200)
-local textexts = nil
-local mptriplet = mp.triplet
-local nbdimensions = nodes.boxes.dimensions
+ local mpprint = aux.print
+ local mpvprint = aux.vprint
-function mp.tt_initialize(tt)
- textexts = tt
-end
+ local hashes = { }
--- function mp.tt_wd(n)
--- local box = textexts and textexts[n]
--- mpprint(box and box.width/factor or 0)
--- end
--- function mp.tt_ht(n)
--- local box = textexts and textexts[n]
--- mpprint(box and box.height/factor or 0)
--- end
--- function mp.tt_dp(n)
--- local box = textexts and textexts[n]
--- mpprint(box and box.depth/factor or 0)
--- end
-
-function mp.tt_dimensions(n)
- local box = textexts and textexts[n]
- if box then
- -- could be made faster with nuts but not critical
- mptriplet(box.width/factor,box.height/factor,box.depth/factor)
- else
- mptriplet(0,0,0)
+ function mp.newhash()
+ for i=1,#hashes+1 do
+ if not hashes[i] then
+ hashes[i] = { }
+ mpvprint(i)
+ return
+ end
+ end
end
-end
-function mp.tb_dimensions(category,name)
- local w, h, d = nbdimensions(category,name)
- mptriplet(w/factor,h/factor,d/factor)
-end
-
-function mp.report(a,b)
- if b then
- report_message("%s : %s",a,b)
- elseif a then
- report_message("%s : %s","message",a)
+ function mp.disposehash(n)
+ hashes[n] = nil
end
-end
-
---
-local hashes = { }
+ function mp.inhash(n,key)
+ local h = hashes[n]
+ mpprint(h and h[key] and true or false)
+ end
-function mp.newhash()
- for i=1,#hashes+1 do
- if not hashes[i] then
- hashes[i] = { }
- mpprint(i)
- return
+ function mp.tohash(n,key)
+ local h = hashes[n]
+ if h then
+ h[key] = true
end
end
-end
-function mp.disposehash(n)
- hashes[n] = nil
end
-function mp.inhash(n,key)
- local h = hashes[n]
- mpprint(h and h[key] and true or false)
-end
+do
+
+ local mpprint = aux.print
+ local modes = tex.modes
+ local systemmodes = tex.systemmodes
-function mp.tohash(n,key)
- local h = hashes[n]
- if h then
- h[key] = true
+ function mp.mode(s)
+ mpprint(modes[s] and true or false)
end
-end
-local modes = tex.modes
-local systemmodes = tex.systemmodes
+ function mp.systemmode(s)
+ mpprint(systemmodes[s] and true or false)
+ end
-function mp.mode(s)
- mpprint(modes[s] and true or false)
-end
+ mp.processingmode = mp.mode
-function mp.systemmode(s)
- mpprint(systemmodes[s] and true or false)
end
-- for alan's nodes:
-function mp.isarray(str)
- mpprint(find(str,"%d") and true or false)
-end
+do
-function mp.prefix(str)
- mpquoted(match(str,"^(.-)[%d%[]") or str)
-end
+ local mpprint = aux.print
+ local mpquoted = aux.quoted
+
+ function mp.isarray(str)
+ mpprint(find(str,"%d") and true or false)
+ end
--- function mp.dimension(str)
--- local n = 0
--- for s in gmatch(str,"%[?%-?%d+%]?") do --todo: lpeg
--- n = n + 1
--- end
--- mpprint(n)
--- end
+ function mp.prefix(str)
+ mpquoted(match(str,"^(.-)[%d%[]") or str)
+ end
-mp.dimension = lpeg.counter(P("[") * lpegpatterns.integer * P("]") + lpegpatterns.integer,mpprint)
+ -- function mp.dimension(str)
+ -- local n = 0
+ -- for s in gmatch(str,"%[?%-?%d+%]?") do --todo: lpeg
+ -- n = n + 1
+ -- end
+ -- mpprint(n)
+ -- end
--- faster and okay as we don't have many variables but probably only
--- basename makes sense and even then it's not called that often
+ mp.dimension = lpeg.counter(P("[") * lpegpatterns.integer * P("]") + lpegpatterns.integer,mpprint)
--- local hash = table.setmetatableindex(function(t,k)
--- local v = find(k,"%d") and true or false
--- t[k] = v
--- return v
--- end)
---
--- function mp.isarray(str)
--- mpprint(hash[str])
--- end
---
--- local hash = table.setmetatableindex(function(t,k)
--- local v = '"' .. (match(k,"^(.-)%d") or k) .. '"'
--- t[k] = v
--- return v
--- end)
---
--- function mp.prefix(str)
--- mpprint(hash[str])
--- end
+ -- faster and okay as we don't have many variables but probably only
+ -- basename makes sense and even then it's not called that often
+
+ -- local hash = table.setmetatableindex(function(t,k)
+ -- local v = find(k,"%d") and true or false
+ -- t[k] = v
+ -- return v
+ -- end)
+ --
+ -- function mp.isarray(str)
+ -- mpprint(hash[str])
+ -- end
+ --
+ -- local hash = table.setmetatableindex(function(t,k)
+ -- local v = '"' .. (match(k,"^(.-)%d") or k) .. '"'
+ -- t[k] = v
+ -- return v
+ -- end)
+ --
+ -- function mp.prefix(str)
+ -- mpprint(hash[str])
+ -- end
+
+end
-local getdimen = tex.getdimen
-local getcount = tex.getcount
-local gettoks = tex.gettoks
-local setdimen = tex.setdimen
-local setcount = tex.setcount
-local settoks = tex.settoks
+do
+
+ local getdimen = tex.getdimen
+ local getcount = tex.getcount
+ local gettoks = tex.gettoks
+ local setdimen = tex.setdimen
+ local setcount = tex.setcount
+ local settoks = tex.settoks
-local mpprint = mp.print
-local mpquoted = mp.quoted
+ local mpprint = mp.print
+ local mpquoted = mp.quoted
-local factor = number.dimenfactors.bp
+ local bpfactor = number.dimenfactors.bp
--- more helpers
+ -- more helpers
-function mp.getdimen(k) mpprint (getdimen(k)*factor) end
-function mp.getcount(k) mpprint (getcount(k)) end
-function mp.gettoks (k) mpquoted(gettoks (k)) end
-function mp.setdimen(k,v) setdimen(k,v/factor) end
-function mp.setcount(k,v) setcount(k,v) end
-function mp.settoks (k,v) settoks (k,v) end
+ function mp.getdimen(k) mpprint (getdimen(k)*bpfactor) end
+ function mp.getcount(k) mpprint (getcount(k)) end
+ function mp.gettoks (k) mpquoted(gettoks (k)) end
--- def foo = lua.mp.foo ... enddef ; % loops due to foo in suffix
+ function mp.setdimen(k,v) setdimen(k,v/factor) end
+ function mp.setcount(k,v) setcount(k,v) end
+ function mp.settoks (k,v) settoks (k,v) end
-mp._get_dimen_ = mp.getdimen
-mp._get_count_ = mp.getcount
-mp._get_toks_ = mp.gettoks
-mp._set_dimen_ = mp.setdimen
-mp._set_count_ = mp.setcount
-mp._set_toks_ = mp.settoks
+ -- def foo = lua.mp.foo ... enddef ; % loops due to foo in suffix
+
+ mp._get_dimen_ = mp.getdimen
+ mp._get_count_ = mp.getcount
+ mp._get_toks_ = mp.gettoks
+ mp._set_dimen_ = mp.setdimen
+ mp._set_count_ = mp.setcount
+ mp._set_toks_ = mp.settoks
+
+end
-- position fun
@@ -796,7 +853,7 @@ do
local mpvprint = mp.vprint
- local stores = { }
+ local stores = { }
function mp.newstore(name)
stores[name] = { }
@@ -826,59 +883,50 @@ end
do
- local mpprint = mp.print
- local texmodes = tex.modes
-
- function mp.processingmode(s)
- mpprint(tostring(texmodes[s]))
- end
-
-end
-
-do
-
-- a bit overkill: just a find(str,"mf_object=") can be enough
- local p1 = P("mf_object=")
- local p2 = lpeg.patterns.eol * p1
- local pattern = (1-p2)^0 * p2 + p1
+ local mpboolean = aux.boolean
+
+ local p1 = P("mf_object=")
+ local p2 = lpegpatterns.eol * p1
+ local pattern = (1-p2)^0 * p2 + p1
function mp.isobject(str)
- mp.boolean(pattern and str ~= "" and lpegmatch(p,str))
+ mpboolean(pattern and str ~= "" and lpegmatch(p,str))
end
end
do
- local mpnumeric = mp.numeric
- local mppair = mp.pair
- local mpgetpath = mp.get.path
+ local mpnumeric = aux.numeric
+ local mppair = aux.pair
+ local mpgetpath = get.path
local p = nil
local n = 0
- function mp.mfun_path_length(name)
- p = mp.get.path(name)
+ local function mf_path_length(name)
+ p = mpgetpath(name)
n = p and #p or 0
mpnumeric(n)
end
- function mp.mfun_path_point(i)
+ local function mf_path_point(i)
if i > 0 and i <= n then
local pi = p[i]
mppair(pi[1],pi[2])
end
end
- function mp.mfun_path_left(i)
+ local function mf_path_left(i)
if i > 0 and i <= n then
local pi = p[i]
mppair(pi[5],pi[6])
end
end
- function mp.mfun_path_right(i)
+ local function mf_path_right(i)
if i > 0 and i <= n then
local pn
if i == 1 then
@@ -890,9 +938,15 @@ do
end
end
- function mp.mfun_path_reset()
+ local function mf_path_reset()
p = nil
n = 0
end
+ mp.mf_path_length = mf_path_length mp.pathlength = mf_path_length
+ mp.mf_path_point = mf_path_point mp.pathpoint = mf_path_point
+ mp.mf_path_left = mf_path_left mp.pathleft = mf_path_left
+ mp.mf_path_right = mf_path_right mp.pathright = mf_path_right
+ mp.mf_path_reset = mf_path_reset mp.pathreset = mf_path_reset
+
end
diff --git a/tex/context/base/mkiv/mlib-pps.lua b/tex/context/base/mkiv/mlib-pps.lua
index 237efe901..39b80e344 100644
--- a/tex/context/base/mkiv/mlib-pps.lua
+++ b/tex/context/base/mkiv/mlib-pps.lua
@@ -101,16 +101,18 @@ local f_f3 = formatters["%.3F"]
local f_gray = formatters["%.3F g %.3F G"]
local f_rgb = formatters["%.3F %.3F %.3F rg %.3F %.3F %.3F RG"]
local f_cmyk = formatters["%.3F %.3F %.3F %.3F k %.3F %.3F %.3F %.3F K"]
-local f_cm = formatters["q %F %F %F %F %F %F cm"]
+local f_cm_b = formatters["q %F %F %F %F %F %F cm"]
local f_shade = formatters["MpSh%s"]
+local s_cm_e = "Q"
+
directives.register("metapost.stripzeros",function()
f_f = formatters["%N"]
f_f3 = formatters["%.3N"]
f_gray = formatters["%.3N g %.3N G"]
f_rgb = formatters["%.3N %.3N %.3N rg %.3N %.3N %.3N RG"]
f_cmyk = formatters["%.3N %.3N %.3N %.3N k %.3N %.3N %.3N %.3N K"]
- f_cm = formatters["q %N %N %N %N %N %N cm"]
+ f_cm_b = formatters["q %N %N %N %N %N %N cm"]
f_shade = formatters["MpSh%s"]
end)
@@ -606,7 +608,7 @@ function metapost.preparetextextsdata()
end
end
end
- mp.tt_initialize(collected)
+ mp.mf_tt_initialize(collected)
end
metapost.intermediate = metapost.intermediate or { }
@@ -989,7 +991,7 @@ local function cm(object)
if op then
local first, second, fourth = op[1], op[2], op[4]
if fourth then
- local tx, ty = first.x_coord , first.y_coord
+ local tx, ty = first.x_coord, first.y_coord
local sx, sy = second.x_coord - tx, fourth.y_coord - ty
local rx, ry = second.y_coord - ty, fourth.x_coord - tx
if sx == 0 then sx = 0.00001 end
@@ -1095,7 +1097,7 @@ local tx_reset, tx_analyze, tx_process do
end
end
- function mp.SomeText(index,str)
+ function mp.mf_some_text(index,str)
mp_target = index
mp_index = index
mp_c = nil
@@ -1111,8 +1113,8 @@ local tx_reset, tx_analyze, tx_process do
local madetext = nil
- function mp.MadeText(index)
- mp.SomeText(index,madetext)
+ function mp.mf_made_text(index)
+ mp.mf_some_text(index,madetext)
end
function metapost.maketext(s,mode)
@@ -1129,7 +1131,7 @@ local tx_reset, tx_analyze, tx_process do
end
end
- function mp.SomeFormattedText(index,fmt,...)
+ function mp.mf_formatted_text(index,fmt,...)
local t = { }
for i=1,select("#",...) do
local ti = select(i,...)
@@ -1139,7 +1141,7 @@ local tx_reset, tx_analyze, tx_process do
end
local f = lpegmatch(cleaner,fmt)
local s = formatters[f](unpack(t)) or ""
- mp.SomeText(index,s)
+ mp.mf_some_text(index,s)
end
interfaces.implement {
@@ -1433,7 +1435,7 @@ local gt_reset, gt_analyze, gt_process do
function metapost.intermediate.actions.makempy()
end
- function mp.GraphicText(index,str)
+ function mp.mf_graphic_text(index,str)
if not graphics[index] then
mp_index = index
mp_str = str
@@ -1613,7 +1615,7 @@ end
local function bm_process(object,prescript,before,after)
local bm_xresolution = prescript.bm_xresolution
if bm_xresolution then
- before[#before+1] = f_cm(cm(object))
+ before[#before+1] = f_cm_b(cm(object))
before[#before+1] = function()
figures.bitmapimage {
xresolution = tonumber(bm_xresolution),
@@ -1623,7 +1625,7 @@ local function bm_process(object,prescript,before,after)
data = object.postscript
}
end
- before[#before+1] = "Q"
+ before[#before+1] = s_cm_e
object.path = false
object.color = false
object.grouped = true
@@ -1651,14 +1653,33 @@ end
-- figures
+-- local sx, rx, ry, sy, tx, ty = cm(object)
+-- sxsy(box.width,box.height,box.depth))
+
+function mp.mf_external_figure(filename)
+ local f = figures.getinfo(filename)
+ local w = 0
+ local h = 0
+ if f then
+ local u = f.used
+ if u and u.fullname then
+ w = u.width or 0
+ h = u.height or 0
+ end
+ else
+ report_metapost("external figure %a not found",filename)
+ end
+ mp.triplet(w/65536,h/65536,0)
+end
+
local function fg_process(object,prescript,before,after)
local fg_name = prescript.fg_name
if fg_name then
- before[#before+1] = f_cm(cm(object)) -- beware: does not use the cm stack
+ before[#before+1] = f_cm_b(cm(object)) -- beware: does not use the cm stack
before[#before+1] = function()
context.MPLIBfigure(fg_name,prescript.fg_mask or "")
end
- before[#before+1] = "Q"
+ before[#before+1] = s_cm_e
object.path = false
object.grouped = true
end
@@ -1835,7 +1856,7 @@ local ot_reset, ot_analyze, ot_process do
local mp_kind = ""
local mp_str = ""
- function mp.OutlineText(index,str,kind)
+ function mp.mf_outline_text(index,str,kind)
if not outlinetexts[index] then
mp_index = index
mp_kind = kind
@@ -1879,7 +1900,7 @@ local ot_reset, ot_analyze, ot_process do
end
}
- function mp.get_outline_text(index) -- maybe we need a more private namespace
+ function mp.mf_get_outline_text(index) -- maybe we need a more private namespace
mp.print(outlinetexts[index] or "draw origin;")
end
diff --git a/tex/context/base/mkiv/mlib-pps.mkiv b/tex/context/base/mkiv/mlib-pps.mkiv
index bc4ce5a04..051130585 100644
--- a/tex/context/base/mkiv/mlib-pps.mkiv
+++ b/tex/context/base/mkiv/mlib-pps.mkiv
@@ -78,10 +78,15 @@
{\clf_mpgettext\MPtextbox #1%
\vpack to \zeropoint{\vss\hpack to \zeropoint{\scale[\c!sx=#2,\c!sy=#3]{\raise\dp\MPtextbox\box\MPtextbox}\forcecolorhack\hss}}}
+% \unexpanded\def\MPLIBfigure#1#2%
+% {\setbox\scratchbox\hpack{\externalfigure[#1][\c!mask=#2]}%
+% \clf_mpsetsxsy\wd\scratchbox\ht\scratchbox\zeropoint
+% \vpack to \zeropoint{\vss\hpack to \zeropoint{\scale[\c!sx=\sx,\c!sy=\sy]{\box\scratchbox}\hss}}}
+
\unexpanded\def\MPLIBfigure#1#2%
{\setbox\scratchbox\hpack{\externalfigure[#1][\c!mask=#2]}%
\clf_mpsetsxsy\wd\scratchbox\ht\scratchbox\zeropoint
- \vpack to \zeropoint{\vss\hpack to \zeropoint{\scale[\c!sx=\sx,\c!sy=\sy]{\box\scratchbox}\hss}}}
+ \vpack to \zeropoint{\vss\hpack to \zeropoint{\fastsxsy{\sx}{\sy}{\box\scratchbox}\hss}}}
% horrible (we could inline scale and matrix code):
diff --git a/tex/context/base/mkiv/mult-prm.mkiv b/tex/context/base/mkiv/mult-prm.mkiv
index 3480cded5..5ffb84d38 100644
--- a/tex/context/base/mkiv/mult-prm.mkiv
+++ b/tex/context/base/mkiv/mult-prm.mkiv
@@ -68,7 +68,7 @@
"pdftracingfonts", "pdftrailer", "pdftrailerid", "pdfuniformdeviate",
"pdfuniqueresname", "pdfvorigin", "pdfxform", "pdfxformattr",
"pdfxformmargin", "pdfxformname", "pdfxformresources", "pdfximage",
- "pdfomitcidset",
+ "pdfomitcidset", "pdfomitcharset",
},
aleph = { -- we don't bother
"Alephminorversion", "Alephrevision", "Alephversion",
diff --git a/tex/context/base/mkiv/mult-sys.mkiv b/tex/context/base/mkiv/mult-sys.mkiv
index 7000eed7b..22c14ff9c 100644
--- a/tex/context/base/mkiv/mult-sys.mkiv
+++ b/tex/context/base/mkiv/mult-sys.mkiv
@@ -240,6 +240,7 @@
\definesystemconstant {next}
\definesystemconstant {pickup}
+\definesystemconstant {forget}
\definesystemconstant {ascii}
\definesystemconstant {default}
\definesystemconstant {unknown}
diff --git a/tex/context/base/mkiv/page-ini.mkiv b/tex/context/base/mkiv/page-ini.mkiv
index dc94edf76..1a9968759 100644
--- a/tex/context/base/mkiv/page-ini.mkiv
+++ b/tex/context/base/mkiv/page-ini.mkiv
@@ -256,7 +256,10 @@
\box\pagebox
\egroup \ifconditional\c_page_boxes_save_page_body \copy\b_page_boxes_saved_page_body \fi}
-\appendtoks \restoreglobalbodyfont \to \everybeforepagebody
+\appendtoks
+ \restoreglobalbodyfont
+ \pickupattributes
+\to \everybeforepagebody
\ifdefined\nestednewbox \else \newbox\nestednextbox \fi % hm, still needed?
diff --git a/tex/context/base/mkiv/scrp-ini.mkiv b/tex/context/base/mkiv/scrp-ini.mkiv
index 8f28f505d..4567e6791 100644
--- a/tex/context/base/mkiv/scrp-ini.mkiv
+++ b/tex/context/base/mkiv/scrp-ini.mkiv
@@ -18,9 +18,9 @@
\registerctxluafile{scrp-eth}{}
\registerctxluafile{scrp-tha}{}
-\definesystemattribute[scriptinjection][public]
-\definesystemattribute[scriptsplitting][public]
-\definesystemattribute[scriptstatus] [public]
+\definesystemattribute[scriptinjection][public,pickup]
+\definesystemattribute[scriptsplitting][public,pickup]
+\definesystemattribute[scriptstatus] [public,pickup]
%D Since scripts need specific \LUA\ code we use hard coded attribute
%D values, but we might have more tricks at some time, so we use a
@@ -43,10 +43,23 @@
\unexpanded\def\scripts_basics_set
{\clf_setscript{\currentscript}{\scriptparameter\c!method}{\scriptparameter\c!preset}}
-\unexpanded\def\setscript[#1]%
+% \unexpanded\def\setscript[#1]%
+% {\edef\currentscript{#1}%
+% \scripts_basics_set}
+
+\unexpanded\def\setglobalscript[#1]%
+ {\edef\currentscript{#1}%
+ \scripts_basics_set
+ \pickupscriptinjectionattribute
+ \pickupscriptsplittingattribute
+ \pickupscriptstatusattribute}
+
+\unexpanded\def\setlocalscript[#1]%
{\edef\currentscript{#1}%
\scripts_basics_set}
+\let\setscript\setlocalscript
+
\unexpanded\def\resetscript
{\clf_resetscript}
diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf
index d94a27382..72d03ba70 100644
--- a/tex/context/base/mkiv/status-files.pdf
+++ b/tex/context/base/mkiv/status-files.pdf
Binary files differ
diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf
index 78ada2867..47a682ba6 100644
--- a/tex/context/base/mkiv/status-lua.pdf
+++ b/tex/context/base/mkiv/status-lua.pdf
Binary files differ
diff --git a/tex/context/base/mkiv/strc-not.mkvi b/tex/context/base/mkiv/strc-not.mkvi
index e2c60d1b1..403247b9c 100644
--- a/tex/context/base/mkiv/strc-not.mkvi
+++ b/tex/context/base/mkiv/strc-not.mkvi
@@ -1057,18 +1057,6 @@
\newskip \s_strc_notes_distance % we need to implement stretch
\newcount\c_strc_notes_columns
-% \def\strc_notes_set_distance
-% {\begingroup
-% \setbox\scratchbox\vbox % no reuse as it can mirror
-% {\forgetall
-% \restoreglobalbodyfont % really needed
-% \dontcomplain
-% \noteparameter\c!before
-% \placenoterule
-% \noteparameter\c!after}%
-% \expandafter\endgroup\expandafter
-% \s_strc_notes_distance\the\htdp\scratchbox\relax} % also dp now
-
\newskip \s_strc_notes_before
\newskip \s_strc_notes_inbetween
\newconditional\c_strc_notes_first_flushed
@@ -1382,19 +1370,22 @@
\fi}
\appendtoks
- \strc_notes_set_penalties
- \forgetall % again
- \strc_notes_set_bodyfont
- \redoconvertfont % to undo \undo calls in in headings etc
- \splittopskip\strutht % not actually needed here
- \splitmaxdepth\strutdp % not actually needed here
- % not:
-% \leftmargindistance \noteparameter\c!margindistance
-% \rightmargindistance\leftmargindistance
-% \ifnum\noteparameter\c!n=\zerocount % no ifcase new 31-07-99 ; always ?
-% \doifnotinset{\noteparameter\c!width}{\v!fit,\v!broad}\setnotehsize % ?
-% \fi
- %
+ \strc_notes_set_penalties
+ \forgetall % again
+ \strc_notes_set_bodyfont
+ \redoconvertfont % to undo \undo calls in in headings etc
+ \splittopskip\strutht % not actually needed here
+ \splitmaxdepth\strutdp % not actually needed here
+ %
+ % not:
+ %
+ % \leftmargindistance \noteparameter\c!margindistance
+ % \rightmargindistance\leftmargindistance
+ % \ifnum\noteparameter\c!n=\zerocount % no ifcase new 31-07-99 ; always ?
+ % \doifnotinset{\noteparameter\c!width}{\v!fit,\v!broad}\setnotehsize % ?
+ % \fi
+ %
+ \pickupattributes
\to \everyinsidenoteinsert
% maybe but better use [scope=local] here
diff --git a/tex/context/base/mkiv/syst-ini.mkiv b/tex/context/base/mkiv/syst-ini.mkiv
index 799fccc7a..6e5ced525 100644
--- a/tex/context/base/mkiv/syst-ini.mkiv
+++ b/tex/context/base/mkiv/syst-ini.mkiv
@@ -605,7 +605,10 @@
%D A few shortcuts:
-\normalprotected\def\glet {\global \let }
+\ifdefined\glet \else
+ \normalprotected\def\glet{\global\let}
+\fi
+
\normalprotected\def\udef {\normalprotected\def }
\normalprotected\def\ugdef{\normalprotected\gdef}
\normalprotected\def\uedef{\normalprotected\edef}
@@ -1107,6 +1110,8 @@
\edef\pdfinclusioncopyfonts {\pdfvariable inclusioncopyfonts} \pdfinclusioncopyfonts \plusone
\edef\pdfinclusionerrorlevel {\pdfvariable inclusionerrorlevel} \pdfinclusionerrorlevel \zerocount
\edef\pdfgentounicode {\pdfvariable gentounicode} \pdfgentounicode \plusone
+%edef\pdfomitcidset {\pdfvariable omitcidset } \pdfomitcidset \zerocount
+%edef\pdfomitcharset {\pdfvariable omitcharset} \pdfomitcharset \plusone
\edef\pdfpagebox {\pdfvariable pagebox} \pdfpagebox \zerocount
\edef\pdfmajorversion {\pdfvariable majorversion} % \pdfmajorversion \plusone
\edef\pdfminorversion {\pdfvariable minorversion} \pdfminorversion \plusseven
diff --git a/tex/context/base/mkiv/typo-dir.mkiv b/tex/context/base/mkiv/typo-dir.mkiv
index dd0a03329..9d8d6b968 100644
--- a/tex/context/base/mkiv/typo-dir.mkiv
+++ b/tex/context/base/mkiv/typo-dir.mkiv
@@ -18,7 +18,7 @@
\unprotect
-\registerctxluafile{typo-dir}{}
+\registerctxluafile{typo-dir}{optimize}
\registerctxluafile{typo-dha}{}
\registerctxluafile{typo-dua}{}
\registerctxluafile{typo-dub}{}
@@ -28,7 +28,7 @@
\registerctxluafile{typo-duc}{}
}
-\definesystemattribute[directions][public,global]
+\definesystemattribute[directions][public,pickup]
\installcorenamespace{directions}
\installcorenamespace{directionsbidimode}
@@ -69,8 +69,9 @@
\expandafter\glet\csname\??directionsbidimode\currentbidistamp\endcsname\currentbidimode}
\appendtoks
+ \edef\p_bidi{\directionsparameter\c!bidi}%
\edef\currentbidistamp
- {\directionsparameter\c!bidi
+ {\p_bidi
:\directionsparameter\c!method
:\directionsparameter\c!fences}%
\expandafter\let\expandafter\currentbidimode\csname\??directionsbidimode\currentbidistamp\endcsname
@@ -83,6 +84,11 @@
\else
\setdirection[\number\directionsbidimode]%
\fi
+ \ifx\p_bidi\v!global
+ \pickupdirectionsattribute
+ \else
+ \forgetdirectionsattribute
+ \fi
\to \everysetupdirections
\appendtoks
diff --git a/tex/context/base/mkiv/typo-mar.mkiv b/tex/context/base/mkiv/typo-mar.mkiv
index f265f173c..10a47e705 100644
--- a/tex/context/base/mkiv/typo-mar.mkiv
+++ b/tex/context/base/mkiv/typo-mar.mkiv
@@ -155,6 +155,7 @@
\forgetall
\tf
\resetallattributes % \deactivatecolor % needed, but maybe we should switch to maintextcolor: \onlyinheritmaintextcolor
+ \pickupattributes
\to \everymargindatacontent
% trialtypesetting: no need for margin stuff while trialing as
diff --git a/tex/context/interface/mkii/keys-de.xml b/tex/context/interface/mkii/keys-de.xml
index 9b742d4b1..e5db3a6f4 100644
--- a/tex/context/interface/mkii/keys-de.xml
+++ b/tex/context/interface/mkii/keys-de.xml
@@ -1033,6 +1033,7 @@
<cd:constant name='otherstext' value='otherstext'/>
<cd:constant name='outermargin' value='outermargin'/>
<cd:constant name='overprint' value='overprint'/>
+ <cd:constant name='ownerpassword' value='ownerpassword'/>
<cd:constant name='ownnumber' value='eigenenummer'/>
<cd:constant name='page' value='seite'/>
<cd:constant name='pageboundaries' value='seitenbegrenzung'/>
@@ -1274,6 +1275,7 @@
<cd:constant name='up' value='up'/>
<cd:constant name='urlalternative' value='urlalternative'/>
<cd:constant name='urlspace' value='urlspatium'/>
+ <cd:constant name='userpassword' value='userpassword'/>
<cd:constant name='validate' value='validieren'/>
<cd:constant name='values' value='values'/>
<cd:constant name='vcommand' value='vbefehl'/>
diff --git a/tex/context/interface/mkiv/i-context.pdf b/tex/context/interface/mkiv/i-context.pdf
index c92ba194a..e12fb62d5 100644
--- a/tex/context/interface/mkiv/i-context.pdf
+++ b/tex/context/interface/mkiv/i-context.pdf
Binary files differ
diff --git a/tex/context/interface/mkiv/i-readme.pdf b/tex/context/interface/mkiv/i-readme.pdf
index 04f5a960f..0d42c03d2 100644
--- a/tex/context/interface/mkiv/i-readme.pdf
+++ b/tex/context/interface/mkiv/i-readme.pdf
Binary files differ
diff --git a/tex/context/modules/mkiv/x-setups-overview.mkiv b/tex/context/modules/mkiv/x-setups-overview.mkiv
index f6dff12f5..512db3bd1 100644
--- a/tex/context/modules/mkiv/x-setups-overview.mkiv
+++ b/tex/context/modules/mkiv/x-setups-overview.mkiv
@@ -102,8 +102,9 @@
numeric h, w; boolean mapping ; path p, q, r ; color f, d ; pair s ;
h := OverlayHeight ; w := 2*OverlayWidth ;
r := unitsquare xyscaled (w,h) ;
- fill r withcolor \MPcolor{lightgray} ;
- mapping := lua.mp.processingmode("setups:mapping") ;
+ fill r withcolor resolvedcolor("lightgray") ;
+ % mapping := lua.mp.processingmode("setups:mapping") ;
+ mapping := lua.mp("processingmode","setups:mapping") ;
if mapping :
set_grid(w,h,w/8,w/160) ;
pickup pensquare yscaled (w/80) ;
@@ -114,8 +115,8 @@
forever :
s := center r randomized (w,h) ;
if new_on_grid(xpart s, ypart s) :
- d := .5[\MPcolor{LocalColor},\MPcolor{lightgray}] randomized (.5,.9) ;
- f := \MPcolor{lightgray} randomized (.5,.9) ;
+ d := .5[resolvedcolor("LocalColor"),resolvedcolor("lightgray")] randomized (.5,.9) ;
+ f := resolvedcolor("lightgray") randomized (.5,.9) ;
s := (dx,dy) ;
if mapping :
p := (-w/4,0) -- (w/4,0) ;
diff --git a/tex/generic/context/luatex/luatex-pdf.tex b/tex/generic/context/luatex/luatex-pdf.tex
index bd6690860..569f8664f 100644
--- a/tex/generic/context/luatex/luatex-pdf.tex
+++ b/tex/generic/context/luatex/luatex-pdf.tex
@@ -135,6 +135,8 @@
\xdef\pdfinclusioncopyfonts {\pdfvariable inclusioncopyfonts}
\xdef\pdfinclusionerrorlevel {\pdfvariable inclusionerrorlevel}
\xdef\pdfgentounicode {\pdfvariable gentounicode}
+ \xdef\pdfomitcidset {\pdfvariable omitcidset}
+ \xdef\pdfomitcharset {\pdfvariable omitcharset}
\xdef\pdfpagebox {\pdfvariable pagebox}
\xdef\pdfmajorversion {\pdfvariable majorversion}
\xdef\pdfminorversion {\pdfvariable minorversion}
@@ -178,6 +180,8 @@
\global\pdfinclusioncopyfonts 0
\global\pdfinclusionerrorlevel 0
\global\pdfgentounicode 0
+ % \global\pdfomitcidset 0
+ % \global\pdfomitcharset 0
\global\pdfpagebox 0
% \global\pdfmajorversion 1
\global\pdfminorversion 4