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

Overview
Comment:Merge the blunder in without documentation.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | schema
Files: files | file ages | folders
SHA3-256: a88689ecce107674754040f3c10b8c552698e6ac6592f421fcbd4a5bbf49f2af
User & Date: rolf 2020-05-02 00:41:31
Context
2020-05-13
23:50
Merged from trunk. check-in: 1fc373ed25 user: rolf tags: schema
2020-05-02
00:51
Merged from schema. check-in: c3fc68e0e2 user: rolf tags: wip
00:41
Merge the blunder in without documentation. check-in: a88689ecce user: rolf tags: schema
00:39
Fix possible subtile bug. Simplified a bit. Closed-Leaf check-in: 37f071d9e0 user: rolf tags: expected-onlymandatory
2020-04-29
18:14
Renamed the command/method deftext to deftexttype. Made it actually work als top level command inside a define script. check-in: bbe36354cb user: rolf tags: schema
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to doc/schema.xml.

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
...
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
...
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
          <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
          frist one 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 string
          any namespace URI arguments are used literally. This is the
          default.
          </desc>
      </commanddef>
................................................................................
                  <desc>Returns in no particular order the defined
                  named pattern in the grammer as list. If a named
                  pattern is namespaced its list entry will be itself
                  a list with two elements, with the name as first and
                  the namespace as second element.</desc>
              </optdef>
              <optdef>
                  <optname>expected</optname> <desc>Returns in no
                  particular order all posible next events (since the
                  last successful event match, if there was one) as a
                  list. If an element is namespaced its list entry
                  will be itself a list with two elements, with the

                  name as first and the namespace as second element.
                  If text is a possible next event the list entry will
                  be a two elements list, with #text as first element
                  and the empty space as second. If an any element
                  constraint is possible the list entry will be a two
                  elements list, with &lt;any> as first element and
                  the empty space as second. If an any element in a
                  certain namespace constraint is possible the list
                  entry will be a two elements list, with &lt;any> as
                  first element and the namespace as second. If
                  element end is a possible event the list entry will
                  be a two elements list with &lt;elementend> and the
                  empty string as second element.</desc>
              </optdef>
              <optdef>
                  <optname>definition name ?namespace?</optname>
                  <desc>Returns the code that defines the given
                  element. The command raises error if there isn't a
                  definition of that element.
................................................................................
                      <dt>NONE</dt><dd>The schema command currently
                      doesn't recover from a validation event.</dd>
                      <dt>MATCH_ELEMENT_START</dt><dd>Element start event, which includs looking for missing or unknown attributes.</dd>
                      <dt>MATCH_ELEMENT_END</dt><dd>Element end event.</dd>
                      <dt>MATCH_TEXT</dt><dd>Validating text between tags.</dd>
                      <dt>MATCH_ATTRIBUTE_TEXT</dt><dd>Attribute text value contraint check</dd>
                      <dt>MATCH_GLOBAL</dt><dd>Checking global IDs</dd>
                      <dt>MATCH_DOM_KEYCONSTRAINT</dt><dd>Checking domuniqe constaint</dd>
                      <dt>MATCH_DOM_XPATH_BOOLEAN</dt><dd>Checking domxpathboolean constaint</dd>
                  </dl>
                  If called with one of the possible optional
                  arguments the command returns detail information
                  depending on current action.
                  <dl>
                      <dt>name</dt><dd>Return the name of the element







|







 







|
|
|
|
|
>
|
|
|
|
|
|
|
|
|
|
|
|







 







|







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
...
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
...
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
          <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
          first one 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 string
          any namespace URI arguments are used literally. This is the
          default.
          </desc>
      </commanddef>
................................................................................
                  <desc>Returns in no particular order the defined
                  named pattern in the grammer as list. If a named
                  pattern is namespaced its list entry will be itself
                  a list with two elements, with the name as first and
                  the namespace as second element.</desc>
              </optdef>
              <optdef>
                  <optname>expected</optname>
                  <desc>Returns in no particular order all posible
                  next events (since the last successful event match,
                  if there was one) as a list. If an element is
                  namespaced its list entry will be itself a list with
                  two elements, with the name as first and the
                  namespace as second element. If text is a possible
                  next event the list entry will be a two elements
                  list, with #text as first element and the empty
                  space as second. If an any element constraint is
                  possible the list entry will be a two elements list,
                  with &lt;any> as first element and the empty space
                  as second. If an any element in a certain namespace
                  constraint is possible the list entry will be a two
                  elements list, with &lt;any> as first element and
                  the namespace as second. If element end is a
                  possible event the list entry will be a two elements
                  list with &lt;elementend> as first element and the
                  empty string as second element.</desc>
              </optdef>
              <optdef>
                  <optname>definition name ?namespace?</optname>
                  <desc>Returns the code that defines the given
                  element. The command raises error if there isn't a
                  definition of that element.
................................................................................
                      <dt>NONE</dt><dd>The schema command currently
                      doesn't recover from a validation event.</dd>
                      <dt>MATCH_ELEMENT_START</dt><dd>Element start event, which includs looking for missing or unknown attributes.</dd>
                      <dt>MATCH_ELEMENT_END</dt><dd>Element end event.</dd>
                      <dt>MATCH_TEXT</dt><dd>Validating text between tags.</dd>
                      <dt>MATCH_ATTRIBUTE_TEXT</dt><dd>Attribute text value contraint check</dd>
                      <dt>MATCH_GLOBAL</dt><dd>Checking global IDs</dd>
                      <dt>MATCH_DOM_KEYCONSTRAINT</dt><dd>Checking domunique constaint</dd>
                      <dt>MATCH_DOM_XPATH_BOOLEAN</dt><dd>Checking domxpathboolean constaint</dd>
                  </dl>
                  If called with one of the possible optional
                  arguments the command returns detail information
                  depending on current action.
                  <dl>
                      <dt>name</dt><dd>Return the name of the element

Changes to generic/schema.c.

204
205
206
207
208
209
210

211
212
213
214
215
216
217
....
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
....
1288
1289
1290
1291
1292
1293
1294




















1295
1296
1297
1298
1299
1300
1301
....
1401
1402
1403
1404
1405
1406
1407
1408





1409
1410
1411
1412
1413
1414
1415
1416
....
1433
1434
1435
1436
1437
1438
1439
1440





1441
1442
1443
1444
1445
1446
1447
1448
....
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
....
1552
1553
1554
1555
1556
1557
1558
1559





1560
1561
1562
1563
1564
1565
1566
1567
....
2234
2235
2236
2237
2238
2239
2240
2241





2242
2243
2244
2245
2246
2247
2248
2249
....
2263
2264
2265
2266
2267
2268
2269
2270





2271
2272
2273
2274
2275
2276
2277
2278
....
2497
2498
2499
2500
2501
2502
2503
2504




2505
2506
2507
2508
2509
2510
2511
2512
....
2532
2533
2534
2535
2536
2537
2538
2539




2540
2541
2542
2543
2544
2545
2546
2547
....
2643
2644
2645
2646
2647
2648
2649
2650




2651
2652
2653
2654
2655
2656
2657
2658
....
3683
3684
3685
3686
3687
3688
3689

3690
3691
3692



3693
3694


3695
3696
3697
3698
3699
3700
3701
....
3708
3709
3710
3711
3712
3713
3714







3715
3716
3717
3718
3719
3720

3721
3722
3723
3724




3725














3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736



3737
3738

3739
3740
3741
3742
3743
3744
3745
3746






3747
3748
3749


































3750

3751
3752

3753
3754
3755
3756
3757


3758
3759
3760

3761
3762




3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774


3775
3776
3777

3778
3779


3780
3781
3782

3783
3784
3785
3786
3787
3788
3789
....
3805
3806
3807
3808
3809
3810
3811
3812

3813
3814
3815
3816
3817
3818
3819
....
3904
3905
3906
3907
3908
3909
3910




3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
/*----------------------------------------------------------------------------
|   [schemacmd info expected] related flags
|
\---------------------------------------------------------------------------*/

#define EXPECTED_IGNORE_MATCHED 1
#define EXPECTED_ONLY_MANDATORY 2


/*----------------------------------------------------------------------------
|   domKeyConstraint related flage
|
\---------------------------------------------------------------------------*/

#define DKC_FLAG_IGNORE_EMPTY_FIELD_SET 1
................................................................................
            se = nextse;
        }
        sdata->lastMatchse = NULL;
        se = sdata->stack->down;
        repoolStackElement (sdata, sdata->stack);
        sdata->stack = se;
    } else {
        if (sdata->stack->activeChild > 0 || sdata->stack->hasMatched) {
            se = sdata->stack->down;
            sdata->stack->down = sdata->lastMatchse;
            sdata->lastMatchse = sdata->stack;
            sdata->stack = se;
        } else {
            se = sdata->stack->down;
            repoolStackElement (sdata, sdata->stack);
................................................................................
    sdata->currentEvals--;
    if (rc != TCL_OK) {
        sdata->evalError = 1;
        return 0;
    }
    return 1;
}





















static int
matchElementStart (
    Tcl_Interp *interp,
    SchemaData *sdata,
    char *name,
    char *namespace
................................................................................
                            return 1;
                        }
                        break;

                    case SCHEMA_CTYPE_CHOICE:
                        Tcl_Panic ("MIXED or CHOICE child of MIXED or CHOICE");

                    case SCHEMA_CTYPE_INTERLEAVE:





                    case SCHEMA_CTYPE_PATTERN:
                        pushToStack (sdata, icp);
                        rc = matchElementStart (interp, sdata, name, namespace);
                        if (rc == 1) {
                            updateStack (sdata, se, ac);
                            return 1;
                        }
                        popStack (sdata);
................................................................................
            case SCHEMA_CTYPE_VIRTUAL:
                if (evalVirtual (interp, sdata, ac)) {
                    hm = 1;
                    break;
                }
                else return 0;

            case SCHEMA_CTYPE_INTERLEAVE:





            case SCHEMA_CTYPE_PATTERN:
                pushToStack (sdata, candidate);
                rc = matchElementStart (interp, sdata, name, namespace);
                if (rc == 1) {
                    updateStack (sdata, se, ac);
                    return 1;
                }
                popStack (sdata);
................................................................................
                hm = 0;
                continue;
            }
            if (!mayskip && mustMatch (cp->quants[ac], hm)) {
                if (recover (interp, sdata, MISSING_ELEMENT_MATCH_START, name,
                             namespace, NULL, ac)) {
                    if (sdata->recoverFlags & RECOVER_FLAG_IGNORE) {
                        /* We pretend the ac content particel had
                         * matched. */
                        updateStack (sdata, se, ac);
                    }
                    return 1;
                }
                return 0;
            }
................................................................................
                    return 1;
                }
                break;

            case SCHEMA_CTYPE_CHOICE:
                Tcl_Panic ("MIXED or CHOICE child of INTERLEAVE");

            case SCHEMA_CTYPE_INTERLEAVE:





            case SCHEMA_CTYPE_PATTERN:
                pushToStack (sdata, icp);
                rc = matchElementStart (interp, sdata, name, namespace);
                if (rc == 1) {
                    if (!(sdata->recoverFlags & RECOVER_FLAG_REWIND)) {
                        se->hasMatched = 1;
                        se->interleaveState[i] = 1;
                    }
................................................................................
                        mayskip = 1;
                        break;

                    case SCHEMA_CTYPE_NAME:
                    case SCHEMA_CTYPE_ANY:
                        continue;
                        
                    case SCHEMA_CTYPE_INTERLEAVE:





                    case SCHEMA_CTYPE_PATTERN:
                        pushToStack (sdata, ic);
                        if (checkElementEnd (interp, sdata)) {
                            mayskip = 1;
                        }
                        popStack (sdata);
                        break;
                        
................................................................................
                }
                break;
                
            case SCHEMA_CTYPE_VIRTUAL:
                if (evalVirtual (interp, sdata, ac)) break;
                else return 0;
                
            case SCHEMA_CTYPE_INTERLEAVE:





            case SCHEMA_CTYPE_PATTERN:
                pushToStack (sdata, cp->content[ac]);
                rc = checkElementEnd (interp, sdata);
                popStack (sdata);
                if (rc) break;
                if (!recover (interp, sdata, MISSING_ELEMENT_MATCH_END, NULL,
                              NULL, NULL, 0)) {
                    return 0;
................................................................................
                            }
                            break;

                        case SCHEMA_CTYPE_NAME:
                        case SCHEMA_CTYPE_ANY:
                            break;

                        case SCHEMA_CTYPE_INTERLEAVE:




                        case SCHEMA_CTYPE_PATTERN:
                            pushToStack (sdata, ic);
                            if (matchText (interp, sdata, text)) {
                                updateStack (sdata, se, ac);
                                return 1;
                            }
                            popStack (sdata);
                            break;
................................................................................
                            return 1;
                        }
                        SetResultV ("Unexpected text content");
                        return 0;
                    }
                    break;

                case SCHEMA_CTYPE_INTERLEAVE:




                case SCHEMA_CTYPE_PATTERN:
                    pushToStack (sdata, candidate);
                    if (matchText (interp, sdata, text)) {
                        updateStack (sdata, se, ac);
                        return 1;
                    }
                    popStack (sdata);
                    if (mustMatch (cp->quants[ac], hm)) {
................................................................................
                    }
                    break;

                case SCHEMA_CTYPE_NAME:
                case SCHEMA_CTYPE_ANY:
                    break;

                case SCHEMA_CTYPE_INTERLEAVE:




                case SCHEMA_CTYPE_PATTERN:
                    pushToStack (sdata, ic);
                    if (matchText (interp, sdata, text)) {
                        updateStack (sdata, se, ac);
                        return 1;
                    }
                    popStack (sdata);
                    break;
................................................................................
    Tcl_Interp *interp,
    Tcl_HashTable *seenCPs,
    Tcl_Obj *rObj,
    int expectedFlags
    )
{
    int ac, hm, i, hnew, mustMatch, mayskip, rc = 1;

    SchemaCP *cp, *ic, *jc;
    SchemaValidationStack *se1;




    getContext (cp, ac, hm);
    if ((expectedFlags & EXPECTED_IGNORE_MATCHED) && hm) {


        ac++;
        hm = 0;
    } else {
        if (hm && maxOne(cp->quants[ac])) {
            ac++;
            hm = 0;
        }
................................................................................
    case SCHEMA_CTYPE_NAME:
    case SCHEMA_CTYPE_PATTERN:
        while (ac < cp->nc) {
            if (se->interleaveState
                && se->interleaveState[ac]
                && maxOne (cp->quants[ac])) {
                ac++;







                continue;
            }
            ic = cp->content[ac];
            mayskip = 0;
            switch (ic->type) {
            case SCHEMA_CTYPE_NAME:

                Tcl_ListObjAppendElement (interp, rObj,
                                          serializeElementName (interp, ic));
                break;
            case SCHEMA_CTYPE_INTERLEAVE:




            case SCHEMA_CTYPE_PATTERN:














                Tcl_CreateHashEntry (seenCPs, ic, &hnew);
                if (hnew) {
                    se1 = getStackElement (sdata, ic);
                    mayskip = getNextExpectedWorker (sdata, se1, interp,
                                                     seenCPs, rObj,
                                                     expectedFlags);
                    repoolStackElement (sdata, se1);
                }
                break;

            case SCHEMA_CTYPE_ANY:



                Tcl_ListObjAppendElement (interp, rObj,
                                          serializeAnyCP (interp, ic));

                break;

            case SCHEMA_CTYPE_TEXT:
                Tcl_ListObjAppendElement (interp, rObj,
                                          serializeTextCP (interp, ic));
                if (ic->nc == 0 || checkText (interp, ic, "")) {
                    mayskip = 1;
                }






                break;
                
            case SCHEMA_CTYPE_CHOICE:


































                if (ic->flags & MIXED_CONTENT) {

                    Tcl_ListObjAppendElement (interp, rObj,
                                              serializeTextCP (interp, NULL));

                }
                for (i = 0; i < ic->nc; i++) {
                    jc = ic->content[i];
                    switch (jc->type) {
                    case SCHEMA_CTYPE_NAME:


                        Tcl_ListObjAppendElement (
                            interp, rObj, serializeElementName (interp, jc)
                            );

                        break;
                    case SCHEMA_CTYPE_INTERLEAVE:




                    case SCHEMA_CTYPE_PATTERN:
                        Tcl_CreateHashEntry (seenCPs, jc, &hnew);
                        if (hnew) {
                            se1 = getStackElement (sdata, ic);
                            mayskip = getNextExpectedWorker (
                                sdata, se1, interp, seenCPs, rObj,
                                expectedFlags
                                );
                            repoolStackElement (sdata, se1);
                        }
                        break;
                    case SCHEMA_CTYPE_ANY:


                        Tcl_ListObjAppendElement (
                            interp, rObj, serializeAnyCP (interp, jc)
                            );

                        break;
                    case SCHEMA_CTYPE_TEXT:


                        Tcl_ListObjAppendElement (
                            interp, rObj, serializeTextCP (interp, jc)
                            );

                        break;
                    case SCHEMA_CTYPE_CHOICE:
                        Tcl_Panic ("MIXED or CHOICE child of MIXED or CHOICE");

                    case SCHEMA_CTYPE_VIRTUAL:
                    case SCHEMA_CTYPE_KEYSPACE:
                    case SCHEMA_CTYPE_KEYSPACE_END:
................................................................................
            }
            ac++;
            hm = 0;
        }
        if (cp->type == SCHEMA_CTYPE_NAME) {
            if (ac == cp->nc) {
                /* The curently open element can end here, no
                 * mandatory elements missing */

                Tcl_ListObjAppendElement (
                    interp, rObj, serializeElementEnd (interp)
                    );
            }
            rc = 0;
        } else if (cp->type == SCHEMA_CTYPE_INTERLEAVE) {
            if (mustMatch) rc = 0;
................................................................................
                remainingLastMatch--;
            } else break;
        }
    }
    
    se = sdata->stack;
    while (se) {




        rc = getNextExpectedWorker (sdata, se, interp, &localHash, rObj,
                                    expectedFlags);
        if (se->pattern->type == SCHEMA_CTYPE_NAME) break;
        se = se->down;
        if (!rc) {
            if (mayMiss(se->pattern->quants[se->activeChild])) continue;
            break;
        }
    }
    Tcl_DeleteHashTable (&localHash);
    Tcl_SetObjResult (interp, unifyMatchList (interp, &localHash, rObj));
    Tcl_DecrRefCount (rObj);
}

static int







>







 







|







 







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







 







|
>
>
>
>
>
|







 







|
>
>
>
>
>
|







 







|







 







|
>
>
>
>
>
|







 







|
>
>
>
>
>
|







 







|
>
>
>
>
>
|







 







|
>
>
>
>
|







 







|
>
>
>
>
|







 







|
>
>
>
>
|







 







>



>
>
>

|
>
>







 







>
>
>
>
>
>
>






>



|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>











>
>
>
|
|
>



<
<



>
>
>
>
>
>



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

>
|
|
>





>
>
|
|
|
>

|
>
>
>
>
|











>
>
|
|
|
>


>
>
|
|
|
>







 







|
>







 







>
>
>
>




|
<
<
<







204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
....
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
....
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
....
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
....
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
....
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
....
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
....
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
....
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
....
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
....
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
....
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
....
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
....
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835


3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
....
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
....
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067



4068
4069
4070
4071
4072
4073
4074
/*----------------------------------------------------------------------------
|   [schemacmd info expected] related flags
|
\---------------------------------------------------------------------------*/

#define EXPECTED_IGNORE_MATCHED 1
#define EXPECTED_ONLY_MANDATORY 2
#define EXPECTED_PROBE_MAYSKIP 4

/*----------------------------------------------------------------------------
|   domKeyConstraint related flage
|
\---------------------------------------------------------------------------*/

#define DKC_FLAG_IGNORE_EMPTY_FIELD_SET 1
................................................................................
            se = nextse;
        }
        sdata->lastMatchse = NULL;
        se = sdata->stack->down;
        repoolStackElement (sdata, sdata->stack);
        sdata->stack = se;
    } else {
        if (sdata->stack->hasMatched) {
            se = sdata->stack->down;
            sdata->stack->down = sdata->lastMatchse;
            sdata->lastMatchse = sdata->stack;
            sdata->stack = se;
        } else {
            se = sdata->stack->down;
            repoolStackElement (sdata, sdata->stack);
................................................................................
    sdata->currentEvals--;
    if (rc != TCL_OK) {
        sdata->evalError = 1;
        return 0;
    }
    return 1;
}

/* Check, if the pattern to probe does not call itself (even
 * indirectly) without a match inbetween.*/
static int inline
recursivePattern (
    SchemaValidationStack *se,
    SchemaCP *pattern
    )
{
    int rc = 0;
    
    while (se && se->pattern->type != SCHEMA_CTYPE_NAME) {
        if (!se->hasMatched && se->pattern == pattern) {
            rc = 1;
            break;
        }
        se = se->down;
    }
    return rc;
}

static int
matchElementStart (
    Tcl_Interp *interp,
    SchemaData *sdata,
    char *name,
    char *namespace
................................................................................
                            return 1;
                        }
                        break;

                    case SCHEMA_CTYPE_CHOICE:
                        Tcl_Panic ("MIXED or CHOICE child of MIXED or CHOICE");

                    case SCHEMA_CTYPE_PATTERN:
                        if (recursivePattern (se, icp)) {
                            mayskip = 1;
                            continue;
                        }
                        /* fall throu */
                    case SCHEMA_CTYPE_INTERLEAVE:
                        pushToStack (sdata, icp);
                        rc = matchElementStart (interp, sdata, name, namespace);
                        if (rc == 1) {
                            updateStack (sdata, se, ac);
                            return 1;
                        }
                        popStack (sdata);
................................................................................
            case SCHEMA_CTYPE_VIRTUAL:
                if (evalVirtual (interp, sdata, ac)) {
                    hm = 1;
                    break;
                }
                else return 0;

            case SCHEMA_CTYPE_PATTERN:
                if (recursivePattern (se, candidate)) {
                    mayskip = 1;
                    break;
                }
                /* fall throu */
            case SCHEMA_CTYPE_INTERLEAVE:
                pushToStack (sdata, candidate);
                rc = matchElementStart (interp, sdata, name, namespace);
                if (rc == 1) {
                    updateStack (sdata, se, ac);
                    return 1;
                }
                popStack (sdata);
................................................................................
                hm = 0;
                continue;
            }
            if (!mayskip && mustMatch (cp->quants[ac], hm)) {
                if (recover (interp, sdata, MISSING_ELEMENT_MATCH_START, name,
                             namespace, NULL, ac)) {
                    if (sdata->recoverFlags & RECOVER_FLAG_IGNORE) {
                        /* We pretend the ac content particle had
                         * matched. */
                        updateStack (sdata, se, ac);
                    }
                    return 1;
                }
                return 0;
            }
................................................................................
                    return 1;
                }
                break;

            case SCHEMA_CTYPE_CHOICE:
                Tcl_Panic ("MIXED or CHOICE child of INTERLEAVE");

            case SCHEMA_CTYPE_PATTERN:
                if (recursivePattern (se, icp)) {
                    mayskip = 1;
                    continue;
                }
                /* fall throu */
            case SCHEMA_CTYPE_INTERLEAVE:
                pushToStack (sdata, icp);
                rc = matchElementStart (interp, sdata, name, namespace);
                if (rc == 1) {
                    if (!(sdata->recoverFlags & RECOVER_FLAG_REWIND)) {
                        se->hasMatched = 1;
                        se->interleaveState[i] = 1;
                    }
................................................................................
                        mayskip = 1;
                        break;

                    case SCHEMA_CTYPE_NAME:
                    case SCHEMA_CTYPE_ANY:
                        continue;
                        
                    case SCHEMA_CTYPE_PATTERN:
                        if (recursivePattern (se, ic)) {
                            mayskip = 1;
                            break;
                        }
                        /* fall throu */
                    case SCHEMA_CTYPE_INTERLEAVE:
                        pushToStack (sdata, ic);
                        if (checkElementEnd (interp, sdata)) {
                            mayskip = 1;
                        }
                        popStack (sdata);
                        break;
                        
................................................................................
                }
                break;
                
            case SCHEMA_CTYPE_VIRTUAL:
                if (evalVirtual (interp, sdata, ac)) break;
                else return 0;
                
            case SCHEMA_CTYPE_PATTERN:
                if (recursivePattern (se, cp->content[ac])) {
                    mayskip = 1;
                    break;
                }
                /* fall throu */
            case SCHEMA_CTYPE_INTERLEAVE:
                pushToStack (sdata, cp->content[ac]);
                rc = checkElementEnd (interp, sdata);
                popStack (sdata);
                if (rc) break;
                if (!recover (interp, sdata, MISSING_ELEMENT_MATCH_END, NULL,
                              NULL, NULL, 0)) {
                    return 0;
................................................................................
                            }
                            break;

                        case SCHEMA_CTYPE_NAME:
                        case SCHEMA_CTYPE_ANY:
                            break;

                        case SCHEMA_CTYPE_PATTERN:
                            if (recursivePattern (se, ic)) {
                                break;
                            }
                            /* fall throu */
                        case SCHEMA_CTYPE_INTERLEAVE:
                            pushToStack (sdata, ic);
                            if (matchText (interp, sdata, text)) {
                                updateStack (sdata, se, ac);
                                return 1;
                            }
                            popStack (sdata);
                            break;
................................................................................
                            return 1;
                        }
                        SetResultV ("Unexpected text content");
                        return 0;
                    }
                    break;

                case SCHEMA_CTYPE_PATTERN:
                    if (recursivePattern (se, candidate)) {
                        break;
                    }
                    /* fall throu */
                case SCHEMA_CTYPE_INTERLEAVE:
                    pushToStack (sdata, candidate);
                    if (matchText (interp, sdata, text)) {
                        updateStack (sdata, se, ac);
                        return 1;
                    }
                    popStack (sdata);
                    if (mustMatch (cp->quants[ac], hm)) {
................................................................................
                    }
                    break;

                case SCHEMA_CTYPE_NAME:
                case SCHEMA_CTYPE_ANY:
                    break;

                case SCHEMA_CTYPE_PATTERN:
                    if (recursivePattern (se, ic)) {
                        break;
                    }
                    /* fall throu */
                case SCHEMA_CTYPE_INTERLEAVE:
                    pushToStack (sdata, ic);
                    if (matchText (interp, sdata, text)) {
                        updateStack (sdata, se, ac);
                        return 1;
                    }
                    popStack (sdata);
                    break;
................................................................................
    Tcl_Interp *interp,
    Tcl_HashTable *seenCPs,
    Tcl_Obj *rObj,
    int expectedFlags
    )
{
    int ac, hm, i, hnew, mustMatch, mayskip, rc = 1;
    int probeMayskip = 0;
    SchemaCP *cp, *ic, *jc;
    SchemaValidationStack *se1;

    if (expectedFlags & EXPECTED_PROBE_MAYSKIP) {
        probeMayskip = 1;
    }
    getContext (cp, ac, hm);
    if ((expectedFlags & EXPECTED_IGNORE_MATCHED
         || expectedFlags & EXPECTED_ONLY_MANDATORY)
        && hm) {
        ac++;
        hm = 0;
    } else {
        if (hm && maxOne(cp->quants[ac])) {
            ac++;
            hm = 0;
        }
................................................................................
    case SCHEMA_CTYPE_NAME:
    case SCHEMA_CTYPE_PATTERN:
        while (ac < cp->nc) {
            if (se->interleaveState
                && se->interleaveState[ac]
                && maxOne (cp->quants[ac])) {
                ac++;
                hm = 0;
                continue;
            }
            if (expectedFlags & EXPECTED_ONLY_MANDATORY
                && !(mustMatch (cp->quants[ac], hm))) {
                ac++;
                hm = 0;
                continue;
            }
            ic = cp->content[ac];
            mayskip = 0;
            switch (ic->type) {
            case SCHEMA_CTYPE_NAME:
                if (probeMayskip) break;
                Tcl_ListObjAppendElement (interp, rObj,
                                          serializeElementName (interp, ic));
                break;
            case SCHEMA_CTYPE_PATTERN:
                if (recursivePattern (se, ic)) {
                    break;
                }
                /* Fall through */
            case SCHEMA_CTYPE_INTERLEAVE:
                if (expectedFlags & EXPECTED_ONLY_MANDATORY
                    && !se->hasMatched) {
                    expectedFlags |= EXPECTED_PROBE_MAYSKIP;
                    se1 = getStackElement (sdata, ic);
                    mayskip = getNextExpectedWorker (sdata, se1, interp,
                                                     seenCPs, rObj,
                                                     expectedFlags);
                    repoolStackElement (sdata, se1);
                    if (!probeMayskip) {
                        expectedFlags &= ~EXPECTED_PROBE_MAYSKIP;
                    }
                    if (mayskip) break;
                }
                if (probeMayskip) break;
                Tcl_CreateHashEntry (seenCPs, ic, &hnew);
                if (hnew) {
                    se1 = getStackElement (sdata, ic);
                    mayskip = getNextExpectedWorker (sdata, se1, interp,
                                                     seenCPs, rObj,
                                                     expectedFlags);
                    repoolStackElement (sdata, se1);
                }
                break;

            case SCHEMA_CTYPE_ANY:
                if (probeMayskip) break;
                if (!(expectedFlags & EXPECTED_ONLY_MANDATORY)
                    || minOne (cp->quants[ac])) {
                    Tcl_ListObjAppendElement (interp, rObj,
                                              serializeAnyCP (interp, ic));
                }
                break;

            case SCHEMA_CTYPE_TEXT:


                if (ic->nc == 0 || checkText (interp, ic, "")) {
                    mayskip = 1;
                }
                if (probeMayskip) break;
                if (!(expectedFlags & EXPECTED_ONLY_MANDATORY)
                    || mayskip == 0) {
                    Tcl_ListObjAppendElement (interp, rObj,
                                              serializeTextCP (interp, ic));
                }
                break;
                
            case SCHEMA_CTYPE_CHOICE:
                if (probeMayskip) {
                    for (i = 0; i < ic->nc; i++) {
                        if (mayMiss (ic->quants[i])) {
                            mayskip = 1;
                            break;
                        }
                        jc = ic->content[i];
                        switch (jc->type) {
                        case SCHEMA_CTYPE_PATTERN:
                            if (recursivePattern (se, ic)) {
                                mayskip = 1;
                                break;
                            }
                            /* fall throu */
                        case SCHEMA_CTYPE_INTERLEAVE:
                            se1 = getStackElement (sdata, ic);
                            mayskip = getNextExpectedWorker (
                                sdata, se1, interp, seenCPs, rObj,
                                expectedFlags
                                );
                            repoolStackElement (sdata, se1);
                            break;
                        case SCHEMA_CTYPE_TEXT:
                            if (ic->nc == 0 || checkText (interp, ic, "")) {
                                mayskip = 1;
                            }
                            break;
                        default:
                            break;
                        }
                        if (mayskip) break;
                    }
                    break;
                }
                if (ic->flags & MIXED_CONTENT) {
                    if (!(expectedFlags & EXPECTED_ONLY_MANDATORY)) {
                        Tcl_ListObjAppendElement (
                            interp, rObj, serializeTextCP (interp, NULL));
                    }
                }
                for (i = 0; i < ic->nc; i++) {
                    jc = ic->content[i];
                    switch (jc->type) {
                    case SCHEMA_CTYPE_NAME:
                        if (!(expectedFlags & EXPECTED_ONLY_MANDATORY)
                            || minOne (cp->quants[i])) {
                            Tcl_ListObjAppendElement (
                                interp, rObj, serializeElementName (interp, jc)
                                );
                        }
                        break;
                    case SCHEMA_CTYPE_PATTERN:
                        if (recursivePattern (se, jc)) {
                            break;
                        }
                        /* Fall through */
                    case SCHEMA_CTYPE_INTERLEAVE:
                        Tcl_CreateHashEntry (seenCPs, jc, &hnew);
                        if (hnew) {
                            se1 = getStackElement (sdata, ic);
                            mayskip = getNextExpectedWorker (
                                sdata, se1, interp, seenCPs, rObj,
                                expectedFlags
                                );
                            repoolStackElement (sdata, se1);
                        }
                        break;
                    case SCHEMA_CTYPE_ANY:
                        if (!(expectedFlags & EXPECTED_ONLY_MANDATORY)
                            || minOne (cp->quants[i])) {
                            Tcl_ListObjAppendElement (
                                interp, rObj, serializeAnyCP (interp, jc)
                                );
                        }
                        break;
                    case SCHEMA_CTYPE_TEXT:
                        if (!(expectedFlags & EXPECTED_ONLY_MANDATORY)
                            || minOne (cp->quants[i])) {
                            Tcl_ListObjAppendElement (
                                interp, rObj, serializeTextCP (interp, jc)
                                );
                        }
                        break;
                    case SCHEMA_CTYPE_CHOICE:
                        Tcl_Panic ("MIXED or CHOICE child of MIXED or CHOICE");

                    case SCHEMA_CTYPE_VIRTUAL:
                    case SCHEMA_CTYPE_KEYSPACE:
                    case SCHEMA_CTYPE_KEYSPACE_END:
................................................................................
            }
            ac++;
            hm = 0;
        }
        if (cp->type == SCHEMA_CTYPE_NAME) {
            if (ac == cp->nc) {
                /* The curently open element can end here, no
                 * mandatory elements missing.
                 * The element end is always mandatory.*/
                Tcl_ListObjAppendElement (
                    interp, rObj, serializeElementEnd (interp)
                    );
            }
            rc = 0;
        } else if (cp->type == SCHEMA_CTYPE_INTERLEAVE) {
            if (mustMatch) rc = 0;
................................................................................
                remainingLastMatch--;
            } else break;
        }
    }
    
    se = sdata->stack;
    while (se) {
        if (!se->hasMatched && se->pattern->type != SCHEMA_CTYPE_NAME) {
            se = se->down;
            continue;
        }
        rc = getNextExpectedWorker (sdata, se, interp, &localHash, rObj,
                                    expectedFlags);
        if (se->pattern->type == SCHEMA_CTYPE_NAME) break;
        se = se->down;
        if (!rc) break;



    }
    Tcl_DeleteHashTable (&localHash);
    Tcl_SetObjResult (interp, unifyMatchList (interp, &localHash, rObj));
    Tcl_DecrRefCount (rObj);
}

static int

Changes to tests/schema.test.

6510
6511
6512
6513
6514
6515
6516
6517
6518
6519
6520
6521
6522
6523
6524
....
6529
6530
6531
6532
6533
6534
6535




















6536
6537
6538
6539
6540
6541
6542
....
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
....
6575
6576
6577
6578
6579
6580
6581























6582
6583
6584
6585
6586
6587
6588
....
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
....
6621
6622
6623
6624
6625
6626
6627























6628
6629
6630
6631
6632
6633
6634
....
6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
....
6678
6679
6680
6681
6682
6683
6684




























6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696
....
6701
6702
6703
6704
6705
6706
6707
6708
6709
6710
6711













































































6712
6713
6714
6715
6716
6717
6718
    }
    s event start doc
    set result [s info expected]
    s delete
    lsort $result
} {a b c musthave toplevel}

test schema-17.5a {info expected} {
    tdom::schema s
    s define {
        defelement doc {
            choice ? {
                element a
                element c
                element b
................................................................................
        }
    }
    s event start doc
    set result [s info expected -ignorematched]
    s delete
    lsort $result
} {a b c musthave toplevel}





















test schema-17.6 {info expected} {
    tdom::schema s
    s prefixns {foo http://foo.bar}
    s define {
        defelement doc {
            choice ? {
................................................................................
    }
    s event start doc
    set result [s info expected]
    s delete
    lsort $result
} {a b c {musthave http://foo.bar} toplevel}

test schema-17.6a {info expected} {
    tdom::schema s
    s prefixns {foo http://foo.bar}
    s define {
        defelement doc {
            choice ? {
                element a
                element c
................................................................................
        }
    }
    s event start doc
    set result [s info expected -ignorematched]
    s delete
    lsort $result
} {a b c {musthave http://foo.bar} toplevel}
























test schema-17.7 {info expected} {
    tdom::schema s
    s prefixns {foo http://foo.bar}
    s define {
        defelement doc {
            mixed {
................................................................................
    }
    s event start doc
    set result [s info expected]
    s delete
    lsort $result
} {a b c {musthave http://foo.bar} toplevel {{#text} {}}}

test schema-17.7a {info expected} {
    tdom::schema s
    s prefixns {foo http://foo.bar}
    s define {
        defelement doc {
            mixed {
                element a
                element c
................................................................................
        }
    }
    s event start doc
    set result [s info expected -ignorematched]
    s delete
    lsort $result
} {a b c {musthave http://foo.bar} toplevel {{#text} {}}}
























test schema-17.8 {info expected} {
    tdom::schema s
    s defelement doc {
        choice ? {
            element a
            element c
................................................................................
    s event start c
    s event end
    lappend result {*}[lsort [s info expected]]
    s delete
    set result
} {doc a b c doc a b c musthave toplevel musthave toplevel}

test schema-17.8a {info expected} {
    tdom::schema s
    s defelement doc {
        choice ? {
            element a
            element c
            element b
        }
................................................................................
    s event start c
    s event end
    lappend result {*}[lsort [s info expected -ignorematched]]
    s delete
    set result
} {doc a b c doc a b c musthave toplevel musthave toplevel}





























proc schema-17.9 {scmd} {
    global result
    lappend result {*}[lsort [$scmd info expected]]
}
                  
test schema-17.9 {info expected from scripted constrain} {
    tdom::schema s
    s define {
        defpattern some {
            element a ?
            group ? {
                element b ?
................................................................................
        defelement doc {
            ref some ?
            element may ?
            element must
        }
    }
    set result ""
    lappend [s validate {<doc><must/></doc>}]
    s delete
    set result
} {a b c may must}














































































test schema-17.10 {info expected interleave} {
    set defs {
        {
            interleave {
                element a ?
                element b







|







 







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







 







|







 







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







 







|







 







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







 







|







 







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




<







 







|


|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







6510
6511
6512
6513
6514
6515
6516
6517
6518
6519
6520
6521
6522
6523
6524
....
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
....
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584
6585
6586
6587
....
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621
6622
6623
6624
6625
6626
6627
6628
6629
6630
6631
....
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653
6654
6655
6656
....
6664
6665
6666
6667
6668
6669
6670
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
6682
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700
....
6716
6717
6718
6719
6720
6721
6722
6723
6724
6725
6726
6727
6728
6729
6730
....
6744
6745
6746
6747
6748
6749
6750
6751
6752
6753
6754
6755
6756
6757
6758
6759
6760
6761
6762
6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775
6776
6777
6778
6779
6780
6781
6782

6783
6784
6785
6786
6787
6788
6789
....
6794
6795
6796
6797
6798
6799
6800
6801
6802
6803
6804
6805
6806
6807
6808
6809
6810
6811
6812
6813
6814
6815
6816
6817
6818
6819
6820
6821
6822
6823
6824
6825
6826
6827
6828
6829
6830
6831
6832
6833
6834
6835
6836
6837
6838
6839
6840
6841
6842
6843
6844
6845
6846
6847
6848
6849
6850
6851
6852
6853
6854
6855
6856
6857
6858
6859
6860
6861
6862
6863
6864
6865
6866
6867
6868
6869
6870
6871
6872
6873
6874
6875
6876
6877
6878
6879
6880
6881
6882
6883
6884
6885
6886
6887
6888
    }
    s event start doc
    set result [s info expected]
    s delete
    lsort $result
} {a b c musthave toplevel}

test schema-17.5a {info expected -ignorematched} {
    tdom::schema s
    s define {
        defelement doc {
            choice ? {
                element a
                element c
                element b
................................................................................
        }
    }
    s event start doc
    set result [s info expected -ignorematched]
    s delete
    lsort $result
} {a b c musthave toplevel}

test schema-17.5b {info expected} {
    tdom::schema s
    s define {
        defelement doc {
            choice ? {
                element a
                element c
                element b
            }
            element toplevel ?
            element musthave
            element aftermust
        }
    }
    s event start doc
    set result [s info expected -onlymandatory]
    s delete
    lsort $result
} {musthave}

test schema-17.6 {info expected} {
    tdom::schema s
    s prefixns {foo http://foo.bar}
    s define {
        defelement doc {
            choice ? {
................................................................................
    }
    s event start doc
    set result [s info expected]
    s delete
    lsort $result
} {a b c {musthave http://foo.bar} toplevel}

test schema-17.6a {info expected -ignorematched} {
    tdom::schema s
    s prefixns {foo http://foo.bar}
    s define {
        defelement doc {
            choice ? {
                element a
                element c
................................................................................
        }
    }
    s event start doc
    set result [s info expected -ignorematched]
    s delete
    lsort $result
} {a b c {musthave http://foo.bar} toplevel}

test schema-17.6b {info expected -onlymandatory} {
    tdom::schema s
    s prefixns {foo http://foo.bar}
    s define {
        defelement doc {
            choice ? {
                element a
                element c
                element b
            }
            element toplevel ?
            namespace foo {
                element musthave
            }
            element aftermust
        }
    }
    s event start doc
    set result [s info expected -onlymandatory]
    s delete
    lsort $result
} {{musthave http://foo.bar}}

test schema-17.7 {info expected} {
    tdom::schema s
    s prefixns {foo http://foo.bar}
    s define {
        defelement doc {
            mixed {
................................................................................
    }
    s event start doc
    set result [s info expected]
    s delete
    lsort $result
} {a b c {musthave http://foo.bar} toplevel {{#text} {}}}

test schema-17.7a {info expected -ignorematched} {
    tdom::schema s
    s prefixns {foo http://foo.bar}
    s define {
        defelement doc {
            mixed {
                element a
                element c
................................................................................
        }
    }
    s event start doc
    set result [s info expected -ignorematched]
    s delete
    lsort $result
} {a b c {musthave http://foo.bar} toplevel {{#text} {}}}

test schema-17.7b {info expected -onlymandatory} {
    tdom::schema s
    s prefixns {foo http://foo.bar}
    s define {
        defelement doc {
            mixed {
                element a
                element c
                element b
            }
            element toplevel ?
            namespace foo {
                element musthave
            }
            element aftermust
        }
    }
    s event start doc
    set result [s info expected -onlymandatory]
    s delete
    lsort $result
} {{musthave http://foo.bar}}

test schema-17.8 {info expected} {
    tdom::schema s
    s defelement doc {
        choice ? {
            element a
            element c
................................................................................
    s event start c
    s event end
    lappend result {*}[lsort [s info expected]]
    s delete
    set result
} {doc a b c doc a b c musthave toplevel musthave toplevel}

test schema-17.8a {info expected -ignorematched} {
    tdom::schema s
    s defelement doc {
        choice ? {
            element a
            element c
            element b
        }
................................................................................
    s event start c
    s event end
    lappend result {*}[lsort [s info expected -ignorematched]]
    s delete
    set result
} {doc a b c doc a b c musthave toplevel musthave toplevel}

test schema-17.8b {info expected -onlymandatory} {
    tdom::schema s
    s defelement doc {
        choice ? {
            element a
            element c
            element b
        }
        element toplevel ?
        element musthave
        element aftermust
    }
    set result [s info expected -ignorematched]
    s define {
        foreach elm {a b c} {
            defelement $elm {}
        }
    }
    lappend result {*}[lsort [s info expected -onlymandatory]]
    s event start doc
    lappend result {*}[lsort [s info expected -onlymandatory]]
    s event start c
    s event end
    lappend result {*}[lsort [s info expected -onlymandatory]]
    s delete
    set result
} {doc a b c doc musthave musthave}

proc schema-17.9 {scmd} {
    global result
    lappend result {*}[lsort [$scmd info expected]]
}

test schema-17.9 {info expected from scripted constrain} {
    tdom::schema s
    s define {
        defpattern some {
            element a ?
            group ? {
                element b ?
................................................................................
        defelement doc {
            ref some ?
            element may ?
            element must
        }
    }
    set result ""
    lappend result [s validate {<doc><must/></doc>}]
    s delete
    set result
} {a b c may must 1}

test schema-17.9.1 {info expected from scripted constrain} {
    tdom::schema s
    s define {
        defpattern some {
            element a ?
            group ? {
                element b ?
                tcl schema-17.9 [self]
            }
            element c
        }
        defelement doc {
            element othermay ?
            ref some ?
            element may ?
            element must
        }
    }
    set result ""
    lappend result [s validate {<doc><must/></doc>}]
    s delete
    set result
} {a b c may must othermay 1}

proc schema-17.9a {scmd} {
    global result
    lappend result {*}[lsort [$scmd info expected -onlymandatory]]
}
test schema-17.9a {info expected from scripted constrain} {
    tdom::schema s
    s define {
        defpattern some {
            element a ?
            group ? {
                element b ?
                tcl schema-17.9a [self]
            }
            element c
        }
        defelement doc {
            ref some ?
            element may ?
            element must
        }
    }
    set result ""
    lappend result [s validate {<doc><must/></doc>}]
    s delete
    set result
} {must 1}

test schema-17.9a.1 {info expected from scripted constrain} {
    tdom::schema s
    s define {
        defpattern some {
            element a ?
            group ? {
                element b ?
                tcl schema-17.9a [self]
            }
            choice ! {
                element c1 
                ref some ?
            }
        }
        defelement doc {
            ref some ?
            element may ?
            element must
        }
    }
    set result ""
    lappend result [s validate {<doc><must/></doc>}]
    s delete
    set result
} {must 1}

test schema-17.10 {info expected interleave} {
    set defs {
        {
            interleave {
                element a ?
                element b