summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/doc/context/sources/general/manuals/xml/xml-mkiv-expressions.tex
blob: b063cab5408818b35cdaf7f7c1055de804f797cf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
\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
\NC \type {depth()}                  \NC number  \NC the depth in the tree of the found element \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