tDOM

Check-in [508a776b44]
Login

Check-in [508a776b44]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Merge from schema.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | localkey
Files: files | file ages | folders
SHA3-256: 508a776b444fb4fbea66e688ae8ea16f2480a0b42602d2547976fa816548a0dc
User & Date: rolf 2019-05-10 00:40:52.647
Context
2019-05-10
00:49
Use the new schema feature prefixns for namespace prefix resolution in local key constraint XPath expressions. check-in: e407c9fd00 user: rolf tags: localkey
00:40
Merge from schema. check-in: 508a776b44 user: rolf tags: localkey
00:36
Added method prefixns to schema cmds. This allows to point to namespace URIs by shortcuts or prefixes. check-in: 74a399d84f user: rolf tags: schema
2019-05-09
19:16
Merged from schema. check-in: 4879bb492b user: rolf tags: localkey
Changes
Unified Diff Ignore Whitespace Patch
Changes to doc/domDoc.xml.
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
asterisk ('*'), then the method returns an unordered list of all
element names of the document, for which the text node children will be
serialized as CDATA section nodes.</desc>
      </commanddef>

      <commanddef>
        <command><method>selectNodesNamespaces</method> <option>?prefixUriList?</option></command>
        <desc>This method allows one to control a document global prefix
        to namespace URI mapping, which will be used for selectNodes
        method calls (on document as well as on all nodes, which
        belongs to the document) if it is not overwritten by using
        the -namespaces option of the selectNodes method. Any
        namespace prefix within an xpath expression will be first
        resolved against this list. If the list binds the same prefix
        to different namespaces, then the first binding will win. If a
        prefix could not resolved against the document global prefix /
        namespaces list, then the namespace definitions in scope of
        the context node will be used to resolve the prefix, as usual.
        If the optional argument <m>prefixUriList</m> is given, then
        the global prefix / namespace list is set to this list and
        returns it. Without the optional argument the method returns
        the current list. The default is the empty list.</desc>







|
|

|
|
|
|
|







318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
asterisk ('*'), then the method returns an unordered list of all
element names of the document, for which the text node children will be
serialized as CDATA section nodes.</desc>
      </commanddef>

      <commanddef>
        <command><method>selectNodesNamespaces</method> <option>?prefixUriList?</option></command>
        <desc>This method gives control to a document global prefix to
        namespace URI mapping, which will be used for selectNodes
        method calls (on document as well as on all nodes, which
        belongs to the document) if it is not overwritten by using the
        -namespaces option of the selectNodes method. Any namespace
        prefix within an xpath expression will be first resolved
        against this list. If the list binds the same prefix to
        different namespaces, then the first binding will win. If a
        prefix could not resolved against the document global prefix /
        namespaces list, then the namespace definitions in scope of
        the context node will be used to resolve the prefix, as usual.
        If the optional argument <m>prefixUriList</m> is given, then
        the global prefix / namespace list is set to this list and
        returns it. Without the optional argument the method returns
        the current list. The default is the empty list.</desc>
Changes to doc/schema.html.
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
<html>
<head>
<link rel="stylesheet" href="manpage.css"><title>tDOM manual: schema</title><meta name="xsl-processor" content="Jochen Loewer ([email protected]), Rolf Ade ([email protected]) et. al."><meta name="generator" content="$RCSfile: tmml-html.xsl,v $ $Revision: 1.11 $"><meta charset="utf-8">
</head><body>
<div class="header">
<div class="navbar" align="center">
<a href="#SECTid0x5563b3e4fb10">NAME</a> · <a href="#SECTid0x5563b3e50170">SYNOPSIS</a> · <a href="#SECTid0x5563b3e4a5f0">DESCRIPTION </a> · <a href="#SECTid0x5563b3ea8fc0">Schema definition scripts</a> · <a href="#SECTid0x5563b3eb12f0">Quantity specifier</a> · <a href="#SECTid0x5563b3eb3180">Text constraint scripts</a> · <a href="#SECTid0x5563b3ebb590">Exampels</a>
</div><hr class="navsep">
</div><div class="body">
  <h2><a name="SECTid0x5563b3e4fb10">NAME</a></h2><p class="namesection">
<b class="names">tdom::schema - </b><br>Create a schema validation command</p>

  <h2><a name="SECTid0x5563b3e50170">SYNOPSIS</a></h2><pre class="syntax">package require tdom

<b class="cmd">tdom::schema</b> <i class="m">?create?</i> <i class="m">cmdName</i>
    </pre>

  <h2><a name="SECTid0x5563b3e4a5f0">DESCRIPTION </a></h2><p>This command creates validation commands with a simple API. The
    validation commands have methods to define a schema and are able
    to validate XML or DOM trees (and to some degree other kind of
    hierarchical data) against this schema.</p><p>Additionally, a validation command may be used as argument to
    the <i class="m">-validateCmd</i> option of the <i class="m">dom parse</i> and the
    <i class="m">expat</i> commands to enable validation additional to what they
    otherwise do.</p><p>The valid methods of the created commands are:</p><dl class="commandlist">




















      
        <dt>
<b class="method">defelement</b> <i class="m">name</i> <i class="m">?namespace?</i> <i class="m">&lt;definition script&gt;</i>
</dt>
        <dd>This method defines the element <i class="m">name</i> (optional in
        the namespace <i class="m">namespace</i>) in the schema. The
        <i class="m">definition script</i> is evaluated and defines the content






|


|


|




|






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
<html>
<head>
<link rel="stylesheet" href="manpage.css"><title>tDOM manual: schema</title><meta name="xsl-processor" content="Jochen Loewer ([email protected]), Rolf Ade ([email protected]) et. al."><meta name="generator" content="$RCSfile: tmml-html.xsl,v $ $Revision: 1.11 $"><meta charset="utf-8">
</head><body>
<div class="header">
<div class="navbar" align="center">
<a href="#SECTid0x55dce5c8db10">NAME</a> · <a href="#SECTid0x55dce5c8e170">SYNOPSIS</a> · <a href="#SECTid0x55dce5c885f0">DESCRIPTION </a> · <a href="#SECTid0x55dce5ce7e60">Schema definition scripts</a> · <a href="#SECTid0x55dce5cf0190">Quantity specifier</a> · <a href="#SECTid0x55dce5cf2020">Text constraint scripts</a> · <a href="#SECTid0x55dce5cfa430">Exampels</a>
</div><hr class="navsep">
</div><div class="body">
  <h2><a name="SECTid0x55dce5c8db10">NAME</a></h2><p class="namesection">
<b class="names">tdom::schema - </b><br>Create a schema validation command</p>

  <h2><a name="SECTid0x55dce5c8e170">SYNOPSIS</a></h2><pre class="syntax">package require tdom

<b class="cmd">tdom::schema</b> <i class="m">?create?</i> <i class="m">cmdName</i>
    </pre>

  <h2><a name="SECTid0x55dce5c885f0">DESCRIPTION </a></h2><p>This command creates validation commands with a simple API. The
    validation commands have methods to define a schema and are able
    to validate XML or DOM trees (and to some degree other kind of
    hierarchical data) against this schema.</p><p>Additionally, a validation command may be used as argument to
    the <i class="m">-validateCmd</i> option of the <i class="m">dom parse</i> and the
    <i class="m">expat</i> commands to enable validation additional to what they
    otherwise do.</p><p>The valid methods of the created commands are:</p><dl class="commandlist">
      
          <dt>
<b class="method">prefixns</b> <i class="m">?prefixUriList?</i>
</dt>

          <dd>This method gives control to a prefix (or
          abbreviation) to namespace URI mapping. Everywhere a
          namespace argument is expected in the schema command methods
          you may use the "prefix" pointing to the namespace
          URI in the current prefixUriList, set by this method. If the
          list map the same prefix to different namespace URIs the
          last won win. If there isn't such a prefix the namespace
          argument is used literally as namespace URI. If the method
          is called without argument it returns the current
          prefixUriList. If the method is called with the empty list
          any namespace URI arguments are used literally. This is the
          default.
          </dd>
      

      
        <dt>
<b class="method">defelement</b> <i class="m">name</i> <i class="m">?namespace?</i> <i class="m">&lt;definition script&gt;</i>
</dt>
        <dd>This method defines the element <i class="m">name</i> (optional in
        the namespace <i class="m">namespace</i>) in the schema. The
        <i class="m">definition script</i> is evaluated and defines the content
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
        <dt><b class="method">reset</b></dt>
        <dd>This method resets the validation command into state
        READY (while preserving the defined grammer).</dd>
      

    </dl>

  <h2><a name="SECTid0x5563b3ea8fc0">Schema definition scripts</a></h2><p>Schema definition scripts are ordinary Tcl scripts that are
    evaluatend in the namespace tdom::schema. The below listed schema
    definition commands in this tcl namespace allow to define a wide
    variety of document structures. Every schema definition command
    establish a validation constraint on the content which has to
    match or must be optional to render the content as valid. It is a
    validation error if the element in the XML source has additional
    (not matched) content.</p><p>The schema definition commands are:</p><dl class="commandlist">







|







185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
        <dt><b class="method">reset</b></dt>
        <dd>This method resets the validation command into state
        READY (while preserving the defined grammer).</dd>
      

    </dl>

  <h2><a name="SECTid0x55dce5ce7e60">Schema definition scripts</a></h2><p>Schema definition scripts are ordinary Tcl scripts that are
    evaluatend in the namespace tdom::schema. The below listed schema
    definition commands in this tcl namespace allow to define a wide
    variety of document structures. Every schema definition command
    establish a validation constraint on the content which has to
    match or must be optional to render the content as valid. It is a
    validation error if the element in the XML source has additional
    (not matched) content.</p><p>The schema definition commands are:</p><dl class="commandlist">
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
        call. This is meant as toplevel command of a <i>schemacmd
        define</i> script. This command is not allowed nested in an
        other definition script command and will raise error, if you
        call it there.</dd>
      
    </dl>

  <h2><a name="SECTid0x5563b3eb12f0">Quantity specifier</a></h2><p>Serveral schema definition commands expects a quantifier as
    one of their arguments, which specifies how often the content
    particle specified by the command is expected. The valid values
    for a <i class="m">quant</i> argument are:</p><dl class="optlist">
      
        <dt><b>!</b></dt>
        <dd>The content particle must occur exactly once in valid
        documents. This is the default, if a quantifier is







|







335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
        call. This is meant as toplevel command of a <i>schemacmd
        define</i> script. This command is not allowed nested in an
        other definition script command and will raise error, if you
        call it there.</dd>
      
    </dl>

  <h2><a name="SECTid0x55dce5cf0190">Quantity specifier</a></h2><p>Serveral schema definition commands expects a quantifier as
    one of their arguments, which specifies how often the content
    particle specified by the command is expected. The valid values
    for a <i class="m">quant</i> argument are:</p><dl class="optlist">
      
        <dt><b>!</b></dt>
        <dd>The content particle must occur exactly once in valid
        documents. This is the default, if a quantifier is
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
        n to m times (both inclusive) in a row in valid documents. The
        quantifier must be a tcl list with two elements. Both elements
        must be integers, with n &gt;= 0 and n &lt; m.</dd>
      
    </dl><p>If an optional quantifier is not given then it defaults to * in
    case of the mixed command and to ! for all other commands.</p>

  <h2><a name="SECTid0x5563b3eb3180">Text constraint scripts</a></h2><p></p><p>The text constraint commands are:</p><dl class="commandlist">
      
        <dt><b class="cmd">isint</b></dt>
        <dd></dd>
      

      
        <dt>







|







380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
        n to m times (both inclusive) in a row in valid documents. The
        quantifier must be a tcl list with two elements. Both elements
        must be integers, with n &gt;= 0 and n &lt; m.</dd>
      
    </dl><p>If an optional quantifier is not given then it defaults to * in
    case of the mixed command and to ! for all other commands.</p>

  <h2><a name="SECTid0x55dce5cf2020">Text constraint scripts</a></h2><p></p><p>The text constraint commands are:</p><dl class="commandlist">
      
        <dt><b class="cmd">isint</b></dt>
        <dd></dd>
      

      
        <dt>
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
        reference to an ID within the document. The referenced ID may
        be later in the document, that the reference. Several
        references within the document to one ID are possible.</dd>
      
      
        <dt><b class="cmd">base64</b></dt>
        <dd>This text constraint match if text is valid according to
        RFC 4648RFC 4648.</dd>
      
    </dl>
  
  <h2><a name="SECTid0x5563b3ebb590">Exampels</a></h2><p>The XML Schema Part 0: Primer Second Edition
    (<a href="https://www.w3.org/TR/xmlschema-0/">https://www.w3.org/TR/xmlschema-0/</a>) starts with this
    example schema:</p><pre class="example">
&lt;xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;

  &lt;xsd:annotation&gt;
    &lt;xsd:documentation xml:lang="en"&gt;
     Purchase order schema for Example.com.







|



|







540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
        reference to an ID within the document. The referenced ID may
        be later in the document, that the reference. Several
        references within the document to one ID are possible.</dd>
      
      
        <dt><b class="cmd">base64</b></dt>
        <dd>This text constraint match if text is valid according to
        RFC 4648.</dd>
      
    </dl>
  
  <h2><a name="SECTid0x55dce5cfa430">Exampels</a></h2><p>The XML Schema Part 0: Primer Second Edition
    (<a href="https://www.w3.org/TR/xmlschema-0/">https://www.w3.org/TR/xmlschema-0/</a>) starts with this
    example schema:</p><pre class="example">
&lt;xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;

  &lt;xsd:annotation&gt;
    &lt;xsd:documentation xml:lang="en"&gt;
     Purchase order schema for Example.com.
Changes to doc/schema.n.
178
179
180
181
182
183
184














185
186
187
188
189
190
191
.PP
Additionally, a validation command may be used as argument to
the \fI-validateCmd\fR option of the \fIdom parse\fR and the
\&\fIexpat\fR commands to enable validation additional to what they
otherwise do.
.PP
The valid methods of the created commands are:














.TP
\&\fB\fBdefelement\fP \fIname\fB \fI?namespace?\fB \fI<definition script>\fB
\&\fRThis method defines the element \fIname\fR (optional in
the namespace \fInamespace\fR) in the schema. The
\&\fIdefinition script\fR is evaluated and defines the content
model of the element. If the \fInamespace\fR argument is
given, any \fIelement\fR or \fIref\fR references in the







>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
.PP
Additionally, a validation command may be used as argument to
the \fI-validateCmd\fR option of the \fIdom parse\fR and the
\&\fIexpat\fR commands to enable validation additional to what they
otherwise do.
.PP
The valid methods of the created commands are:
.TP
\&\fB\fBprefixns\fP \fI?prefixUriList?\fB
\&\fRThis method gives control to a prefix (or
abbreviation) to namespace URI mapping. Everywhere a
namespace argument is expected in the schema command methods
you may use the "prefix" pointing to the namespace
URI in the current prefixUriList, set by this method. If the
list map the same prefix to different namespace URIs the
last won win. If there isn't such a prefix the namespace
argument is used literally as namespace URI. If the method
is called without argument it returns the current
prefixUriList. If the method is called with the empty list
any namespace URI arguments are used literally. This is the
default.
.TP
\&\fB\fBdefelement\fP \fIname\fB \fI?namespace?\fB \fI<definition script>\fB
\&\fRThis method defines the element \fIname\fR (optional in
the namespace \fInamespace\fR) in the schema. The
\&\fIdefinition script\fR is evaluated and defines the content
model of the element. If the \fInamespace\fR argument is
given, any \fIelement\fR or \fIref\fR references in the
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
\&\fRThis text constraint command expects the text to be a
reference to an ID within the document. The referenced ID may
be later in the document, that the reference. Several
references within the document to one ID are possible.
.TP
\&\fB\fBbase64\fP
\&\fRThis text constraint match if text is valid according to
RFC 4648RFC 4648.
.SH Exampels
.PP
.UR "https://www.w3.org/TR/xmlschema-0/"
<URL: https://www.w3.org/TR/xmlschema-0/>
.UE
The XML Schema Part 0: Primer Second Edition
() starts with this







|







552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
\&\fRThis text constraint command expects the text to be a
reference to an ID within the document. The referenced ID may
be later in the document, that the reference. Several
references within the document to one ID are possible.
.TP
\&\fB\fBbase64\fP
\&\fRThis text constraint match if text is valid according to
RFC 4648.
.SH Exampels
.PP
.UR "https://www.w3.org/TR/xmlschema-0/"
<URL: https://www.w3.org/TR/xmlschema-0/>
.UE
The XML Schema Part 0: Primer Second Edition
() starts with this
Changes to doc/schema.xml.
24
25
26
27
28
29
30


















31
32
33
34
35
36
37
    the <m>-validateCmd</m> option of the <m>dom parse</m> and the
    <m>expat</m> commands to enable validation additional to what they
    otherwise do.</p>

    <p>The valid methods of the created commands are:</p>

    <commandlist>


















      <commanddef>
        <command><method>defelement</method> <m>name</m> <m>?namespace?</m> <m>&lt;definition script></m></command>
        <desc>This method defines the element <m>name</m> (optional in
        the namespace <m>namespace</m>) in the schema. The
        <m>definition script</m> is evaluated and defines the content
        model of the element. If the <m>namespace</m> argument is
        given, any <m>element</m> or <m>ref</m> references in the







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
    the <m>-validateCmd</m> option of the <m>dom parse</m> and the
    <m>expat</m> commands to enable validation additional to what they
    otherwise do.</p>

    <p>The valid methods of the created commands are:</p>

    <commandlist>
      <commanddef>
          <command><method>prefixns</method> <m>?prefixUriList?</m></command>

          <desc>This method gives control to a prefix (or
          abbreviation) to namespace URI mapping. Everywhere a
          namespace argument is expected in the schema command methods
          you may use the &quot;prefix&quot; pointing to the namespace
          URI in the current prefixUriList, set by this method. If the
          list map the same prefix to different namespace URIs the
          last won win. If there isn't such a prefix the namespace
          argument is used literally as namespace URI. If the method
          is called without argument it returns the current
          prefixUriList. If the method is called with the empty list
          any namespace URI arguments are used literally. This is the
          default.
          </desc>
      </commanddef>

      <commanddef>
        <command><method>defelement</method> <m>name</m> <m>?namespace?</m> <m>&lt;definition script></m></command>
        <desc>This method defines the element <m>name</m> (optional in
        the namespace <m>namespace</m>) in the schema. The
        <m>definition script</m> is evaluated and defines the content
        model of the element. If the <m>namespace</m> argument is
        given, any <m>element</m> or <m>ref</m> references in the
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
        reference to an ID within the document. The referenced ID may
        be later in the document, that the reference. Several
        references within the document to one ID are possible.</desc>
      </commanddef>
      <commanddef>
        <command><cmd>base64</cmd></command>
        <desc>This text constraint match if text is valid according to
        RFC 4648RFC 4648.</desc>
      </commanddef>
    </commandlist>
  </section>
  
  <section>
    <title>Exampels</title>








|







497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
        reference to an ID within the document. The referenced ID may
        be later in the document, that the reference. Several
        references within the document to one ID are possible.</desc>
      </commanddef>
      <commanddef>
        <command><cmd>base64</cmd></command>
        <desc>This text constraint match if text is valid according to
        RFC 4648.</desc>
      </commanddef>
    </commandlist>
  </section>
  
  <section>
    <title>Exampels</title>

Changes to generic/schema.c.
423
424
425
426
427
428
429

430
431
432
433
434
435
436

    sdata = TMALLOC (SchemaData);
    memset (sdata, 0, sizeof(SchemaData));
    name = Tcl_GetStringFromObj (cmdNameObj, &len);
    sdata->self = Tcl_NewStringObj (name, len);
    Tcl_IncrRefCount (sdata->self);
    Tcl_InitHashTable (&sdata->element, TCL_STRING_KEYS);

    Tcl_InitHashTable (&sdata->pattern, TCL_STRING_KEYS);
    Tcl_InitHashTable (&sdata->attrNames, TCL_STRING_KEYS);
    Tcl_InitHashTable (&sdata->namespace, TCL_STRING_KEYS);
    Tcl_InitHashTable (&sdata->textDef, TCL_STRING_KEYS);
    sdata->emptyNamespace = Tcl_CreateHashEntry (
        &sdata->namespace, "", &hnew);
    sdata->patternList = (SchemaCP **) MALLOC (







>







423
424
425
426
427
428
429
430
431
432
433
434
435
436
437

    sdata = TMALLOC (SchemaData);
    memset (sdata, 0, sizeof(SchemaData));
    name = Tcl_GetStringFromObj (cmdNameObj, &len);
    sdata->self = Tcl_NewStringObj (name, len);
    Tcl_IncrRefCount (sdata->self);
    Tcl_InitHashTable (&sdata->element, TCL_STRING_KEYS);
    Tcl_InitHashTable (&sdata->prefix, TCL_STRING_KEYS);
    Tcl_InitHashTable (&sdata->pattern, TCL_STRING_KEYS);
    Tcl_InitHashTable (&sdata->attrNames, TCL_STRING_KEYS);
    Tcl_InitHashTable (&sdata->namespace, TCL_STRING_KEYS);
    Tcl_InitHashTable (&sdata->textDef, TCL_STRING_KEYS);
    sdata->emptyNamespace = Tcl_CreateHashEntry (
        &sdata->namespace, "", &hnew);
    sdata->patternList = (SchemaCP **) MALLOC (
477
478
479
480
481
482
483






484

485
486

487
488
489
490
491
492
493
     * schemaInstanceCmd(). */
    if (sdata->currentEvals) {
        sdata->cleanupAfterEval = 1;
        return;
    }
    Tcl_DecrRefCount (sdata->self);
    if (sdata->start) FREE (sdata->start);






    if (sdata->startNamespace) FREE (sdata->startNamespace);

    Tcl_DeleteHashTable (&sdata->namespace);
    Tcl_DeleteHashTable (&sdata->element);

    Tcl_DeleteHashTable (&sdata->pattern);
    Tcl_DeleteHashTable (&sdata->attrNames);
    Tcl_DeleteHashTable (&sdata->textDef);
    for (i = 0; i < sdata->numPatternList; i++) {
        freeSchemaCP (sdata->patternList[i]);
    }
    FREE (sdata->patternList);







>
>
>
>
>
>
|
>


>







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
     * schemaInstanceCmd(). */
    if (sdata->currentEvals) {
        sdata->cleanupAfterEval = 1;
        return;
    }
    Tcl_DecrRefCount (sdata->self);
    if (sdata->start) FREE (sdata->start);
    if (sdata->prefixns) {
        i = 0;
        while (sdata->prefixns[i]) {
            FREE (sdata->prefixns[i]);
            i++;
        }
        FREE (sdata->prefixns);
    }
    Tcl_DeleteHashTable (&sdata->namespace);
    Tcl_DeleteHashTable (&sdata->element);
    Tcl_DeleteHashTable (&sdata->prefix);
    Tcl_DeleteHashTable (&sdata->pattern);
    Tcl_DeleteHashTable (&sdata->attrNames);
    Tcl_DeleteHashTable (&sdata->textDef);
    for (i = 0; i < sdata->numPatternList; i++) {
        freeSchemaCP (sdata->patternList[i]);
    }
    FREE (sdata->patternList);
998
999
1000
1001
1002
1003
1004





















1005
1006
1007
1008
1009
1010
1011
            sdata->skipDeep = 2;
            return 1;
        }
    }
    
    return -1;
}






















int
probeElement (
    Tcl_Interp *interp,
    SchemaData *sdata,
    const char *name,
    void *namespace







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
            sdata->skipDeep = 2;
            return 1;
        }
    }
    
    return -1;
}

static void *
getNamespacePtr (
    SchemaData *sdata,
    char *ns
    )
{
    Tcl_HashEntry *h;
    int hnew;

    if (!ns) return NULL;
    h = Tcl_FindHashEntry (&sdata->prefix, ns);
    if (h) {
        return Tcl_GetHashValue (h);
    }
    h = Tcl_CreateHashEntry (&sdata->namespace, ns, &hnew);
    if (h != sdata->emptyNamespace) {
        return Tcl_GetHashKey (&sdata->namespace, h);
    }
    return NULL;
}

int
probeElement (
    Tcl_Interp *interp,
    SchemaData *sdata,
    const char *name,
    void *namespace
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
    }

    DBG(
        fprintf (stderr, "probeElement: look if '%s' in ns '%s' match\n",
                 name, (char *)namespace);
        );

    if (namespace) {
        entryPtr = Tcl_FindHashEntry (&sdata->namespace, (char *)namespace);
        if (!entryPtr) {
            SetResult ("No elements defined in this namespace");
            return TCL_ERROR;
        }
        if (entryPtr == sdata->emptyNamespace) {
            namespacePtr = NULL;
        } else {
            namespacePtr = Tcl_GetHashKey (&sdata->namespace, entryPtr);
        }
    } else {
        namespacePtr = NULL;
    }
    entryPtr = Tcl_FindHashEntry (&sdata->element, name);
    if (entryPtr) {
        namePtr = Tcl_GetHashKey (&sdata->element, entryPtr);
    } else {
        namePtr = NULL;
    }

    if (sdata->validationState == VALIDATION_READY) {
        /* The root of the tree to check. */
        if (sdata->start) {
            if (strcmp (name, sdata->start) != 0) {
                SetResult ("Root element doesn't match");
                return TCL_ERROR;
            }
            if (namespace) {
                if (!sdata->startNamespace ||
                    strcmp (namespace, sdata->startNamespace) != 0) {
                    SetResult ("Root element namespace doesn't match");
                    return TCL_ERROR;
                }
            } else {
                if (sdata->startNamespace) {
                    SetResult ("Root element namespace doesn't match");







<
<
<
<
<
<
<
|
<
<
<
<
<
<















|







1056
1057
1058
1059
1060
1061
1062







1063






1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
    }

    DBG(
        fprintf (stderr, "probeElement: look if '%s' in ns '%s' match\n",
                 name, (char *)namespace);
        );








    namespacePtr = getNamespacePtr (sdata, namespace);






    entryPtr = Tcl_FindHashEntry (&sdata->element, name);
    if (entryPtr) {
        namePtr = Tcl_GetHashKey (&sdata->element, entryPtr);
    } else {
        namePtr = NULL;
    }

    if (sdata->validationState == VALIDATION_READY) {
        /* The root of the tree to check. */
        if (sdata->start) {
            if (strcmp (name, sdata->start) != 0) {
                SetResult ("Root element doesn't match");
                return TCL_ERROR;
            }
            if (namespace) {
                if (!sdata->startNamespace||
                    strcmp (namespace, sdata->startNamespace) != 0) {
                    SetResult ("Root element namespace doesn't match");
                    return TCL_ERROR;
                }
            } else {
                if (sdata->startNamespace) {
                    SetResult ("Root element namespace doesn't match");
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263

2264
2265
2266
2267
2268
2269
2270
{
    int            methodIndex, keywordIndex, hnew, patternIndex;
    int            result = TCL_OK, forwardDef = 0, i = 0;
    int            savedDefineToplevel, type, len;
    unsigned int   savedNumPatternList;
    SchemaData    *savedsdata = NULL, *sdata = (SchemaData *) clientData;
    Tcl_HashTable *hashTable;
    Tcl_HashEntry *h;
    SchemaCP      *pattern, *current = NULL;
    void          *namespacePtr, *savedNamespacePtr;
    char          *xmlstr, *errMsg;
    domDocument   *doc;
    domNode       *node;

    static const char *schemaInstanceMethods[] = {
        "defelement", "defpattern",  "start",   "event", "delete",
        "nrForwardDefinitions",      "state",   "reset", "define",
        "validate",   "domvalidate", "deftext", "info",  "reportcmd",
        NULL
    };
    enum schemaInstanceMethod {
        m_defelement,  m_defpattern,  m_start,   m_event, m_delete,
        m_nrForwardDefinitions,       m_state,   m_reset, m_define,
        m_validate,    m_domvalidate, m_deftext, m_info,  m_reportcmd

    };

    static const char *eventKeywords[] = {
        "start", "end", "text", NULL
    };

    enum eventKeyword







|










|




|
>







2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
{
    int            methodIndex, keywordIndex, hnew, patternIndex;
    int            result = TCL_OK, forwardDef = 0, i = 0;
    int            savedDefineToplevel, type, len;
    unsigned int   savedNumPatternList;
    SchemaData    *savedsdata = NULL, *sdata = (SchemaData *) clientData;
    Tcl_HashTable *hashTable;
    Tcl_HashEntry *h, *h1;
    SchemaCP      *pattern, *current = NULL;
    void          *namespacePtr, *savedNamespacePtr;
    char          *xmlstr, *errMsg;
    domDocument   *doc;
    domNode       *node;

    static const char *schemaInstanceMethods[] = {
        "defelement", "defpattern",  "start",   "event", "delete",
        "nrForwardDefinitions",      "state",   "reset", "define",
        "validate",   "domvalidate", "deftext", "info",  "reportcmd",
        "prefixns",   NULL
    };
    enum schemaInstanceMethod {
        m_defelement,  m_defpattern,  m_start,   m_event, m_delete,
        m_nrForwardDefinitions,       m_state,   m_reset, m_define,
        m_validate,    m_domvalidate, m_deftext, m_info,  m_reportcmd,
        m_prefixns
    };

    static const char *eventKeywords[] = {
        "start", "end", "text", NULL
    };

    enum eventKeyword
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
            type = SCHEMA_CTYPE_PATTERN;
        }
        savedNumPatternList = sdata->numPatternList;
        namespacePtr = NULL;
        patternIndex = 3-i;
        if (objc == 5-i) {
            patternIndex = 4-i;
            h = Tcl_CreateHashEntry (&sdata->namespace,
                                            Tcl_GetString (objv[3-i]), &hnew);
            if (h != sdata->emptyNamespace) {
                namespacePtr = Tcl_GetHashKey (&sdata->namespace, h);
            }
        }
        h = Tcl_CreateHashEntry (hashTable, Tcl_GetString (objv[2-i]), &hnew);
        pattern = NULL;
        if (!hnew) {
            pattern = (SchemaCP *) Tcl_GetHashValue (h);
            while (pattern) {
                if (pattern->namespace == namespacePtr) {







<
|
<
<
<







2330
2331
2332
2333
2334
2335
2336

2337



2338
2339
2340
2341
2342
2343
2344
            type = SCHEMA_CTYPE_PATTERN;
        }
        savedNumPatternList = sdata->numPatternList;
        namespacePtr = NULL;
        patternIndex = 3-i;
        if (objc == 5-i) {
            patternIndex = 4-i;

            namespacePtr = getNamespacePtr (sdata, Tcl_GetString (objv[3-i]));



        }
        h = Tcl_CreateHashEntry (hashTable, Tcl_GetString (objv[2-i]), &hnew);
        pattern = NULL;
        if (!hnew) {
            pattern = (SchemaCP *) Tcl_GetHashValue (h);
            while (pattern) {
                if (pattern->namespace == namespacePtr) {
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
                              " ?<namespace>?");
            return TCL_ERROR;
        }
        if (sdata->start) {
            FREE (sdata->start);
        }
        if (objc == 3-i && strcmp (Tcl_GetString (objv[2-i]), "") == 0) {
            if (sdata->startNamespace) {
                FREE (sdata->startNamespace);
            }
            sdata->start = NULL;
            break;
        }
        sdata->start = tdomstrdup (Tcl_GetString (objv[2-i]));
        if (objc == 4-i) {
            if (sdata->startNamespace) {
                FREE (sdata->startNamespace);
            }
            sdata->startNamespace =
                tdomstrdup (Tcl_GetString (objv[3-i]));
        }
        break;

    case m_event:
        CHECK_EVAL
        if (objc < 3) {
            Tcl_WrongNumArgs (interp, 2, objv, "<eventType>"







|
<
<





<
<
<

|







2476
2477
2478
2479
2480
2481
2482
2483


2484
2485
2486
2487
2488



2489
2490
2491
2492
2493
2494
2495
2496
2497
                              " ?<namespace>?");
            return TCL_ERROR;
        }
        if (sdata->start) {
            FREE (sdata->start);
        }
        if (objc == 3-i && strcmp (Tcl_GetString (objv[2-i]), "") == 0) {
            sdata->startNamespace = NULL;


            sdata->start = NULL;
            break;
        }
        sdata->start = tdomstrdup (Tcl_GetString (objv[2-i]));
        if (objc == 4-i) {



            sdata->startNamespace =
                getNamespacePtr (sdata, Tcl_GetString (objv[3-i]));
        }
        break;

    case m_event:
        CHECK_EVAL
        if (objc < 3) {
            Tcl_WrongNumArgs (interp, 2, objv, "<eventType>"
2497
2498
2499
2500
2501
2502
2503

2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
        switch ((enum eventKeyword) keywordIndex) {
        case k_elementstart:
            if (objc < 4 && objc > 6) {
                Tcl_WrongNumArgs (interp, 3, objv, "<elementname>"
                    "?<attInfo>? ?<namespace>?");
                return TCL_ERROR;
            }

            if (objc == 6) {
                h = Tcl_FindHashEntry (&sdata->namespace,
                                              Tcl_GetString (objv[5]));
                if (h && h != sdata->emptyNamespace) {
                     namespacePtr = Tcl_GetHashKey (&sdata->namespace, h);
                } else {
                    namespacePtr = NULL;
                }
            } else {
                namespacePtr = NULL;
            }
            result = probeElement (interp, sdata, Tcl_GetString (objv[3]),
                                   namespacePtr);
            break;
        case k_elementend:
            if (objc != 3) {
                Tcl_WrongNumArgs (interp, 3, objv, "No arguments expected.");







>

|
|
<
<
<
<
<
<
<







2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516







2517
2518
2519
2520
2521
2522
2523
        switch ((enum eventKeyword) keywordIndex) {
        case k_elementstart:
            if (objc < 4 && objc > 6) {
                Tcl_WrongNumArgs (interp, 3, objv, "<elementname>"
                    "?<attInfo>? ?<namespace>?");
                return TCL_ERROR;
            }
            namespacePtr = NULL;
            if (objc == 6) {
                namespacePtr = getNamespacePtr (sdata,
                                                Tcl_GetString (objv[5]));







            }
            result = probeElement (interp, sdata, Tcl_GetString (objv[3]),
                                   namespacePtr);
            break;
        case k_elementend:
            if (objc != 3) {
                Tcl_WrongNumArgs (interp, 3, objv, "No arguments expected.");
2643
2644
2645
2646
2647
2648
2649




















2650
2651
2652
2653
2654
2655
2656
        if (sdata->reportCmd) {
            Tcl_DecrRefCount (sdata->reportCmd);
        }
        sdata->reportCmd = objv[2];
        Tcl_IncrRefCount (sdata->reportCmd);
        break;





















    default:
        Tcl_SetResult (interp, "unknown method", NULL);
        result = TCL_ERROR;
        break;

    }
    if (sdata->cleanupAfterEval && sdata->currentEvals == 0) {







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
        if (sdata->reportCmd) {
            Tcl_DecrRefCount (sdata->reportCmd);
        }
        sdata->reportCmd = objv[2];
        Tcl_IncrRefCount (sdata->reportCmd);
        break;

    case m_prefixns:
        result = tcldom_prefixNSlist (&sdata->prefixns, interp, objc, objv,
                                      "prefixns");
        if (sdata->prefix.numBuckets) {
            Tcl_DeleteHashTable (&sdata->prefix);
            Tcl_InitHashTable (&sdata->prefix, TCL_STRING_KEYS);
        }
        if (result == TCL_OK && sdata->prefixns) {
            i = 0;
            while (sdata->prefixns[i]) {
                h = Tcl_CreateHashEntry (&sdata->namespace,
                                         sdata->prefixns[i+1], &hnew);
                h1 = Tcl_CreateHashEntry (&sdata->prefix,
                                          sdata->prefixns[i], &hnew);
                Tcl_SetHashValue (h1, Tcl_GetHashKey (&sdata->namespace, h));
                i += 2;
            }
        }
        break;
        
    default:
        Tcl_SetResult (interp, "unknown method", NULL);
        result = TCL_ERROR;
        break;

    }
    if (sdata->cleanupAfterEval && sdata->currentEvals == 0) {
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
    Tcl_Obj *namespaceObj,
    Tcl_Obj *scriptObj,
    int required,
    SchemaCP *type
    )
{
    Tcl_HashEntry *h;
    int hnew, hnew1, i, result = TCL_OK;
    char *name, *namespace = NULL;
    SchemaAttr *attr;
    SchemaCP *cp;

    if (namespaceObj) {
        h = Tcl_CreateHashEntry (&sdata->namespace,
                                 Tcl_GetString (namespaceObj), &hnew1);
        if (h != sdata->emptyNamespace) {
            namespace = Tcl_GetHashKey (&sdata->namespace, h);
        }
    }
    h = Tcl_CreateHashEntry (&sdata->attrNames,
                             Tcl_GetString (nameObj), &hnew);
    name = Tcl_GetHashKey (&sdata->attrNames, h);
    if (!hnew) {
        /* Check, if there is already an attribute with this name
         * / namespace */







|





|
|
<
<
<







3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079



3080
3081
3082
3083
3084
3085
3086
    Tcl_Obj *namespaceObj,
    Tcl_Obj *scriptObj,
    int required,
    SchemaCP *type
    )
{
    Tcl_HashEntry *h;
    int hnew, i, result = TCL_OK;
    char *name, *namespace = NULL;
    SchemaAttr *attr;
    SchemaCP *cp;

    if (namespaceObj) {
        namespace = getNamespacePtr (sdata,
                                     Tcl_GetString (namespaceObj));



    }
    h = Tcl_CreateHashEntry (&sdata->attrNames,
                             Tcl_GetString (nameObj), &hnew);
    name = Tcl_GetHashKey (&sdata->attrNames, h);
    if (!hnew) {
        /* Check, if there is already an attribute with this name
         * / namespace */
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[]
    )
{
    SchemaData *sdata = GETASI;
    char *currentNamespace;
    Tcl_HashEntry *entryPtr;
    int hnew, result;

    CHECK_SI
    CHECK_TOPLEVEL
    checkNrArgs (3,3,"Expected: namespace pattern");

    currentNamespace = sdata->currentNamespace;
    entryPtr = Tcl_CreateHashEntry (&sdata->namespace,
                                    Tcl_GetString(objv[1]), &hnew);
    if (entryPtr == sdata->emptyNamespace) {
        sdata->currentNamespace = NULL;
    } else {
        sdata->currentNamespace = (char *)
            Tcl_GetHashKey (&sdata->namespace, entryPtr);
    }
    sdata->currentEvals++;
    result = Tcl_EvalObjEx (interp, objv[2], TCL_EVAL_DIRECT);
    sdata->currentEvals--;
    sdata->currentNamespace = currentNamespace;
    return result;
}








<
|






<
<
<
|
<
|
<
<







3222
3223
3224
3225
3226
3227
3228

3229
3230
3231
3232
3233
3234
3235



3236

3237


3238
3239
3240
3241
3242
3243
3244
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[]
    )
{
    SchemaData *sdata = GETASI;
    char *currentNamespace;

    int result;

    CHECK_SI
    CHECK_TOPLEVEL
    checkNrArgs (3,3,"Expected: namespace pattern");

    currentNamespace = sdata->currentNamespace;



    sdata->currentNamespace =

        getNamespacePtr (sdata, Tcl_GetString(objv[1]));


    sdata->currentEvals++;
    result = Tcl_EvalObjEx (interp, objv[2], TCL_EVAL_DIRECT);
    sdata->currentEvals--;
    sdata->currentNamespace = currentNamespace;
    return result;
}

Changes to generic/schema.h.
116
117
118
119
120
121
122


123
124
125
126
127
128
129
{
    Tcl_Obj *self;
    char *start;
    char *startNamespace;
    Tcl_HashTable element;
    Tcl_HashTable namespace;
    Tcl_HashEntry *emptyNamespace;


    Tcl_HashTable pattern;
    Tcl_HashTable attrNames;
    Tcl_HashTable textDef;
    SchemaCP **patternList; 
    unsigned int numPatternList;
    unsigned int patternListSize;
    unsigned int forwardPatternDefs;







>
>







116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
{
    Tcl_Obj *self;
    char *start;
    char *startNamespace;
    Tcl_HashTable element;
    Tcl_HashTable namespace;
    Tcl_HashEntry *emptyNamespace;
    char **prefixns;
    Tcl_HashTable prefix;
    Tcl_HashTable pattern;
    Tcl_HashTable attrNames;
    Tcl_HashTable textDef;
    SchemaCP **patternList; 
    unsigned int numPatternList;
    unsigned int patternListSize;
    unsigned int forwardPatternDefs;
Changes to tests/schema.test.
228
229
230
231
232
233
234
























235
236
237
238
239
240
241
        {<doc><a/><b/></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 1 1 0}

























test schema-1.15 {call structure constraint outside define/defelement} {
    set result [catch {tdom::schema::element foo} errMsg]
    lappend result $errMsg
    tdom::schema create grammar
    lappend result [catch {tdom::schema::element foo} errMsg]
    lappend result $errMsg







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
        {<doc><a/><b/></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 1 1 0}

test schema-1.14a {define start w/ namespace} {
    tdom::schema create s
    s prefixns {ns1 http://foo.bar}
    s start doc ns1
    s defelement doc ns1 {
        element a
        element b
    }
    foreach elm {a b} {
        s defelement $elm ns1 {}
    }
    set result [list]
    foreach xml {
        {<doc xmlns="http://foo.bar"><a/><b/></doc>}
        {<a:doc xmlns:a="http://foo.bar"><a:a/><a:b/></a:doc>}
        {<a:doc xmlns:a="http://foo.bar"><a xmlns="http://foo.bar"/><a:b/></a:doc>}
        {<doc><a/><b/></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1 1 1 0}

test schema-1.15 {call structure constraint outside define/defelement} {
    set result [catch {tdom::schema::element foo} errMsg]
    lappend result $errMsg
    tdom::schema create grammar
    lappend result [catch {tdom::schema::element foo} errMsg]
    lappend result $errMsg
2200
2201
2202
2203
2204
2205
2206
















2207
2208
2209
2210
2211
2212
2213
            }
        }
    }
    set result [s validate {<doc><e foo="bar"/></doc>} errMsg]
    s delete
    lappend result $errMsg
} {1 {}}

















test schema-11.4a {attribute} {
    tdom::schema create s
    s define {
        defelement doc {
            element e 1 {
                attribute foo







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
            }
        }
    }
    set result [s validate {<doc><e foo="bar"/></doc>} errMsg]
    s delete
    lappend result $errMsg
} {1 {}}

test schema-11.4_1 {attribute} {
    tdom::schema create s
    s prefixns {1 http://www.w3.org/XML/1998/namespace}
    s define {
        defelement doc {
            element e 1 {
                attribute foo
                nsattribute lang 1 ?
            }
        }
    }
    set result [s validate {<doc><e foo="bar"/></doc>} errMsg]
    s delete
    lappend result $errMsg
} {1 {}}

test schema-11.4a {attribute} {
    tdom::schema create s
    s define {
        defelement doc {
            element e 1 {
                attribute foo
2247
2248
2249
2250
2251
2252
2253

















2254
2255
2256
2257
2258
2259
2260
2261
2262
2263


























2264
2265
2266
2267
2268
2269
2270
        }
    }
    set result [catch {set doc [dom parse -validateCmd s {<doc><e xml:lang="en" foo="bar"/></doc>}]}]
    s delete
    $doc delete
    set result
} 0


















test schema-11.6 {nsattribute} {
    tdom::schema create s
    s define {
        defelement doc {
            element e 1 {
                attribute foo
                nsattribute lang http://www.w3.org/XML/1998/namespace
            }
        }


























    }
    set result [list]
    foreach xml {
        {<doc><e foo="bar"/></doc>}
        {<doc><e xml:lang="en"/></doc>}
        {<doc><e unknown="some"/></doc>}
        {<doc><e/></doc>}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>










>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
        }
    }
    set result [catch {set doc [dom parse -validateCmd s {<doc><e xml:lang="en" foo="bar"/></doc>}]}]
    s delete
    $doc delete
    set result
} 0

test schema-11.5a {nsattribute} {
    tdom::schema create s
    s prefixns {ns1 http://www.w3.org/XML/1998/namespace}
    s define {
        defelement doc {
            element e 1 {
                attribute foo
                nsattribute lang ns1 ?
            }
        }
    }
    set result [catch {set doc [dom parse -validateCmd s {<doc><e xml:lang="en" foo="bar"/></doc>}]}]
    s delete
    $doc delete
    set result
} 0

test schema-11.6 {nsattribute} {
    tdom::schema create s
    s define {
        defelement doc {
            element e 1 {
                attribute foo
                nsattribute lang http://www.w3.org/XML/1998/namespace
            }
        }
    }
    set result [list]
    foreach xml {
        {<doc><e foo="bar"/></doc>}
        {<doc><e xml:lang="en"/></doc>}
        {<doc><e unknown="some"/></doc>}
        {<doc><e/></doc>}
    } {
        lappend result [catch {set doc [dom parse -validateCmd s $xml]} errMsg]
        lappend result $errMsg
        s reset
    }
    s delete
    set result
} {1 {Missing mandatory attribute(s): http://www.w3.org/XML/1998/namespace:lang, referenced at line 1 character 19} 1 {Missing mandatory attribute(s): foo, referenced at line 1 character 23} 1 {Unknown attribute "unknown", referenced at line 1 character 24} 1 {Missing mandatory attribute(s): foo http://www.w3.org/XML/1998/namespace:lang, referenced at line 1 character 9}}

test schema-11.6 {nsattribute} {
    tdom::schema create s
    s prefixns {ns1 http://www.w3.org/XML/1998/namespace}
    s define {
        defelement doc {
            element e 1 {
                attribute foo
                nsattribute lang ns1
            }
        }
    }
    set result [list]
    foreach xml {
        {<doc><e foo="bar"/></doc>}
        {<doc><e xml:lang="en"/></doc>}
        {<doc><e unknown="some"/></doc>}
        {<doc><e/></doc>}
2413
2414
2415
2416
2417
2418
2419





















































2420
2421
2422
2423
2424
2425
2426
        defelement card http://foo.bar {
            element name
            element email
        }
        foreach e {name email} {
            defelement $e http://foo.bar {text}
        }





















































    }
    set doc [dom parse {
<addressBook xmlns="http://foo.bar">
  <card>
    <name>John Smith</name>
    <email>[email protected]</email>
  </card>







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
        defelement card http://foo.bar {
            element name
            element email
        }
        foreach e {name email} {
            defelement $e http://foo.bar {text}
        }
    }
    set doc [dom parse {
<addressBook xmlns="http://foo.bar">
  <card>
    <name>John Smith</name>
    <email>[email protected]</email>
  </card>
  <card>
    <name>Fred Bloggs</name>
    <email>[email protected]</email>
  </card>
</addressBook>        
    }]
    set result [s domvalidate $doc]
    lappend result [s domvalidate [$doc documentElement]]
    lappend result [s domvalidate [[$doc documentElement] firstChild]]
    lappend result [s domvalidate [[[$doc documentElement] firstChild] firstChild]]
    $doc delete
    set doc [dom parse {
<ns1:addressBook xmlns:ns1="http://foo.bar">
  <ns1:card>
    <ns1:name>John Smith</ns1:name>
    <ns1:email>[email protected]</ns1:email>
  </ns1:card>
  <ns1:card>
    <ns1:name>Fred Bloggs</ns1:name>
    <ns1:email>[email protected]</ns1:email>
  </ns1:card>
</ns1:addressBook>        
}]
    lappend result [s domvalidate $doc]
    lappend result [s domvalidate [$doc documentElement]]
    lappend result [s domvalidate [[$doc documentElement] firstChild]]
    lappend result [s domvalidate [[[$doc documentElement] firstChild] firstChild]]
    $doc delete
    s delete
    set result
} {1 1 1 1 1 1 1 1}

test schema-12.5a {domvalidate doch w/ xml namespace} {
    tdom::schema s 
    s prefixns {fb http://foo.bar}
    s define {
        defelement addressBook fb {
            element card *
        }
        defelement card fb {
            element name
            element email
        }
        foreach e {name email} {
            defelement $e fb {text}
        }
    }
    set doc [dom parse {
<addressBook xmlns="http://foo.bar">
  <card>
    <name>John Smith</name>
    <email>[email protected]</email>
  </card>