tDOM

Check-in [6b550b98f8]
Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to [email protected]
or submit via the online form by Sep 9.

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

Overview
Comment:Enhanced the text constraint commands id/idref: Beside the one doc wide ID space there are now additional other named doc wide ID/IDREF spaces possible. Each of them work along the unnamed doc wide ID space.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | schema
Files: files | file ages | folders
SHA3-256: 6b550b98f8375f99016b8ab33987cdeba487d80ad403246173453a47f7589542
User & Date: rolf 2019-05-14 20:02:51
Context
2019-05-21
22:30
Added dom tree validation specific unique key contraints along the lines of xsd unqiue with selector and list of fields but with no restrictions on the XPath expressions (other then resulting a node set in case of selector and a result set with one node in case of field XPath expression). check-in: ba6bd2bb7c user: rolf tags: schema
16:21
Adding DOM tree postvalidation (only) local key constraints along the lines of xsd unqiue with selector and list of fields but with no restrictions on the XPath expressions (other then resulting a node set in case of selector and a result set with one node in case of field XPath expression). check-in: f645e5dfe1 user: rolf tags: domlocalkey
2019-05-14
20:04
Merge from schema. check-in: dc36b35000 user: rolf tags: localkey
20:02
Enhanced the text constraint commands id/idref: Beside the one doc wide ID space there are now additional other named doc wide ID/IDREF spaces possible. Each of them work along the unnamed doc wide ID space. check-in: 6b550b98f8 user: rolf tags: schema
2019-05-10
13:40
Fixed bug (invalid mem access) if a virtual constraint will be called under certain circumstances while looking if pcdata matches. check-in: 4cc96fcd33 user: rolf tags: schema
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to generic/schema.c.

   436    436       sdata->patternList = (SchemaCP **) MALLOC (
   437    437           sizeof (SchemaCP*) * ANON_PATTERN_ARRAY_SIZE_INIT);
   438    438       sdata->patternListSize = ANON_PATTERN_ARRAY_SIZE_INIT;
   439    439       sdata->quants = (SchemaQuant *) MALLOC (
   440    440           sizeof (SchemaQuant) * QUANTS_ARRAY_SIZE_INIT);
   441    441       sdata->quantsSize = QUANTS_ARRAY_SIZE_INIT;
   442    442       /* evalStub initialization */
   443         -    sdata->evalStub = (Tcl_Obj **) (MALLOC (sizeof (Tcl_Obj*) * 4));
          443  +    sdata->evalStub = (Tcl_Obj **) MALLOC (sizeof (Tcl_Obj*) * 4);
   444    444       sdata->evalStub[0] = Tcl_NewStringObj("::namespace", 11);
   445    445       Tcl_IncrRefCount (sdata->evalStub[0]);
   446    446       sdata->evalStub[1] = Tcl_NewStringObj("eval", 4);
   447    447       Tcl_IncrRefCount (sdata->evalStub[1]);
   448    448       sdata->evalStub[2] = Tcl_NewStringObj("::tdom::schema", 14);
   449    449       Tcl_IncrRefCount (sdata->evalStub[2]);
   450    450       /* textStub initialization */
   451         -    sdata->textStub = (Tcl_Obj **) (MALLOC (sizeof (Tcl_Obj*) * 4));
          451  +    sdata->textStub = (Tcl_Obj **) MALLOC (sizeof (Tcl_Obj*) * 4);
   452    452       sdata->textStub[0] = Tcl_NewStringObj("::namespace", 11);
   453    453       Tcl_IncrRefCount (sdata->textStub[0]);
   454    454       sdata->textStub[1] = Tcl_NewStringObj("eval", 4);
   455    455       Tcl_IncrRefCount (sdata->textStub[1]);
   456    456       sdata->textStub[2] = Tcl_NewStringObj("::tdom::schema::text", 20);
   457    457       Tcl_IncrRefCount (sdata->textStub[2]);
   458         -
   459    458       sdata->cdata = TMALLOC (Tcl_DString);
   460    459       Tcl_DStringInit (sdata->cdata);
   461    460       Tcl_InitHashTable (&sdata->ids, TCL_STRING_KEYS);
   462    461       sdata->unknownIDrefs = 0;
          462  +    Tcl_InitHashTable (&sdata->idTables, TCL_STRING_KEYS);
   463    463       return sdata;
   464    464   }
   465    465   
   466    466   static void schemaInstanceDelete (
   467    467       ClientData clientData
   468    468       )
   469    469   {
   470    470       SchemaData *sdata = (SchemaData *) clientData;
   471    471       unsigned int i;
   472    472       SchemaValidationStack *down;
          473  +    Tcl_HashEntry *h;
          474  +    Tcl_HashSearch search;
          475  +    SchemaDocKey *dk;
   473    476   
   474    477       /* Protect the clientData to be freed inside (even nested)
   475    478        * Tcl_Eval*() calls to avoid invalid mem access and postpone the
   476    479        * cleanup until the Tcl_Eval*() calls are finished (done in
   477    480        * schemaInstanceCmd(). */
   478    481       if (sdata->currentEvals) {
   479    482           sdata->cleanupAfterEval = 1;
................................................................................
   523    526       FREE (sdata->textStub);
   524    527       Tcl_DStringFree (sdata->cdata);
   525    528       FREE (sdata->cdata);
   526    529       if (sdata->reportCmd) {
   527    530           Tcl_DecrRefCount (sdata->reportCmd);
   528    531       }
   529    532       Tcl_DeleteHashTable (&sdata->ids);
          533  +    for (h = Tcl_FirstHashEntry (&sdata->idTables, &search);
          534  +         h != NULL;
          535  +         h = Tcl_NextHashEntry (&search)) {
          536  +        dk = Tcl_GetHashValue (h);
          537  +        Tcl_DeleteHashTable (&dk->ids);
          538  +        FREE (dk);
          539  +    }
          540  +    Tcl_DeleteHashTable (&sdata->idTables);
   530    541       FREE (sdata);
   531    542   }
   532    543   
   533    544   static void
   534    545   cleanupLastPattern (
   535    546       SchemaData *sdata,
   536    547       unsigned int from
   537    548       )
   538    549   {
   539    550       unsigned int i;
   540    551       Tcl_HashTable *hashTable;
   541    552       Tcl_HashEntry *entryPtr;
          553  +
   542    554       SchemaCP *this, *previous, *current;
   543    555   
   544    556       for (i = from; i < sdata->numPatternList; i++) {
   545    557           this = sdata->patternList[i];
   546    558           hashTable = NULL;
   547    559           if (this->type == SCHEMA_CTYPE_NAME) {
   548    560               hashTable = &sdata->element;
................................................................................
  1524   1536                   return 0;
  1525   1537               }
  1526   1538           }
  1527   1539           return -1;
  1528   1540       }
  1529   1541       return 0;
  1530   1542   }
         1543  +
         1544  +static int
         1545  +checkDocKeys (
         1546  +    Tcl_Interp *interp,
         1547  +    SchemaData *sdata
         1548  +    ) 
         1549  +{
         1550  +    Tcl_HashEntry *h, *h1;
         1551  +    Tcl_HashSearch search, search1;
         1552  +    int haveErrMsg = 0;
         1553  +    SchemaDocKey *dk;
         1554  +
         1555  +    if (sdata->unknownIDrefs) {
         1556  +        haveErrMsg = 1;
         1557  +        SetResult ("References to unknown IDs:");
         1558  +        for (h = Tcl_FirstHashEntry (&sdata->ids, &search);
         1559  +             h != NULL;
         1560  +             h = Tcl_NextHashEntry (&search)) {
         1561  +            if (Tcl_GetHashValue (h) == 0) {
         1562  +                Tcl_AppendResult (interp, " '",
         1563  +                                  Tcl_GetHashKey (&sdata->ids, h),
         1564  +                                  "'", NULL);
         1565  +            }
         1566  +        }
         1567  +    }
         1568  +    if (sdata->idTables.numEntries) {
         1569  +        for (h = Tcl_FirstHashEntry (&sdata->idTables, &search);
         1570  +             h != NULL;
         1571  +             h = Tcl_NextHashEntry (&search)) {
         1572  +            dk = Tcl_GetHashValue (h);
         1573  +            if (dk->unknownIDrefs) {
         1574  +                if (haveErrMsg) {
         1575  +                    Tcl_AppendResult (interp, "\n", NULL);
         1576  +                } else {
         1577  +                    haveErrMsg = 1;
         1578  +                }
         1579  +                Tcl_AppendResult (interp,
         1580  +                                  "References to unknown IDs in ID space '",
         1581  +                                  Tcl_GetHashKey (&sdata->idTables, h),
         1582  +                                  "':", NULL);
         1583  +                for (h1 = Tcl_FirstHashEntry (&dk->ids, &search1);
         1584  +                     h1 != NULL;
         1585  +                     h1 = Tcl_NextHashEntry (&search1)) {
         1586  +                    if (Tcl_GetHashValue (h1) == 0) {
         1587  +                        Tcl_AppendResult (interp, " '",
         1588  +                                          Tcl_GetHashKey (&dk->ids, h1),
         1589  +                                          "'", NULL);
         1590  +                    }
         1591  +                }
         1592  +            }
         1593  +        }
         1594  +    }
         1595  +    if (haveErrMsg) {
         1596  +        sdata->validationState = VALIDATION_ERROR;
         1597  +        return 0;
         1598  +    }
         1599  +    return 1;
         1600  +}
  1531   1601   
  1532   1602   int
  1533   1603   probeElementEnd (
  1534   1604       Tcl_Interp *interp,
  1535   1605       SchemaData *sdata
  1536   1606       )
  1537   1607   {
................................................................................
  1566   1636       }
  1567   1637   
  1568   1638       if (rc) {
  1569   1639           popStack (sdata);
  1570   1640           if (sdata->stack == NULL) {
  1571   1641               /* End of the first pattern (the tree root) without error. */
  1572   1642               /* Check for unknown ID references */
  1573         -            if (sdata->unknownIDrefs) {
  1574         -                Tcl_HashEntry *h;
  1575         -                Tcl_HashSearch search;
  1576         -                SetResult ("References to unknown IDs:");
  1577         -                for (h = Tcl_FirstHashEntry (&sdata->ids, &search);
  1578         -                     h != NULL;
  1579         -                     h = Tcl_NextHashEntry (&search)) {
  1580         -                    if (Tcl_GetHashValue (h) == 0) {
  1581         -                        Tcl_AppendResult (interp, " '",
  1582         -                                          Tcl_GetHashKey (&sdata->ids, h),
  1583         -                                          "'", NULL);
  1584         -                    }
  1585         -                }
  1586         -                sdata->validationState = VALIDATION_ERROR;
         1643  +            if (!checkDocKeys (interp, sdata)) {
  1587   1644                   return TCL_ERROR;
  1588   1645               }
  1589   1646               /*  We have successfully ended validation */
  1590   1647               sdata->validationState = VALIDATION_FINISHED;
  1591   1648           }
  1592   1649           DBG(
  1593   1650               fprintf(stderr, "probeElementEnd: _CAN_ end here.\n");
................................................................................
  2105   2162   }
  2106   2163   
  2107   2164   void
  2108   2165   schemaReset (
  2109   2166       SchemaData *sdata
  2110   2167       )
  2111   2168   {
         2169  +    Tcl_HashEntry *h;
         2170  +    Tcl_HashSearch search;
         2171  +    SchemaDocKey *dk;
         2172  +    
  2112   2173       while (sdata->stack) popStack (sdata);
  2113   2174       sdata->validationState = VALIDATION_READY;
  2114   2175       sdata->skipDeep = 0;
  2115   2176       sdata->evalError = 0;
  2116   2177       Tcl_DStringSetLength (sdata->cdata, 0);
  2117   2178       if (sdata->ids.numEntries) {
  2118   2179           Tcl_DeleteHashTable (&sdata->ids);
  2119   2180           Tcl_InitHashTable (&sdata->ids, TCL_STRING_KEYS);
  2120   2181           sdata->unknownIDrefs = 0;
         2182  +    }
         2183  +    if (sdata->idTables.numEntries) {
         2184  +        for (h = Tcl_FirstHashEntry (&sdata->idTables, &search);
         2185  +             h != NULL;
         2186  +             h = Tcl_NextHashEntry (&search)) {
         2187  +            dk = Tcl_GetHashValue (h);
         2188  +            if (&dk->ids.numEntries) {
         2189  +                Tcl_DeleteHashTable (&dk->ids);
         2190  +                Tcl_InitHashTable (&dk->ids, TCL_STRING_KEYS);
         2191  +                dk->unknownIDrefs = 0;
         2192  +            }
         2193  +        }
  2121   2194       }
  2122   2195   }
  2123   2196   
  2124   2197   static int
  2125   2198   evalConstraints (
  2126   2199       Tcl_Interp *interp,
  2127   2200       SchemaData *sdata,
................................................................................
  2659   2732           if (objc != 2-i && objc != 3-i) {
  2660   2733               Tcl_WrongNumArgs (interp, 2-i, objv, "?prefixUriList?");
  2661   2734               return TCL_ERROR;
  2662   2735           }
  2663   2736           if (!i) {objc--; objv++;}
  2664   2737           result = tcldom_prefixNSlist (&sdata->prefixns, interp, objc, objv,
  2665   2738                                         "prefixns");
  2666         -        if (sdata->prefix.numBuckets) {
         2739  +        if (sdata->prefix.numEntries) {
  2667   2740               Tcl_DeleteHashTable (&sdata->prefix);
  2668   2741               Tcl_InitHashTable (&sdata->prefix, TCL_STRING_KEYS);
  2669   2742           }
  2670   2743           if (result == TCL_OK && sdata->prefixns) {
  2671   2744               j = 0;
  2672   2745               while (sdata->prefixns[j]) {
  2673   2746                   h1 = Tcl_CreateHashEntry (&sdata->prefix,
................................................................................
  4388   4461           sdata->unknownIDrefs--;
  4389   4462           return 1;
  4390   4463       } else {
  4391   4464           /* Duplicate ID value */
  4392   4465           return 0;
  4393   4466       }
  4394   4467   }
         4468  +
         4469  +static int
         4470  +docidImpl (
         4471  +    Tcl_Interp *interp,
         4472  +    void *constraintData,
         4473  +    char *text
         4474  +    )
         4475  +{
         4476  +    SchemaDocKey *dk = (SchemaDocKey *) constraintData;
         4477  +    int hnew;
         4478  +    Tcl_HashEntry *h;
         4479  +
         4480  +    h = Tcl_CreateHashEntry (&dk->ids, text, &hnew);
         4481  +    if (hnew) {
         4482  +        Tcl_SetHashValue (h, 1);
         4483  +        return 1;
         4484  +    }
         4485  +    if (Tcl_GetHashValue (h) == 0) {
         4486  +        Tcl_SetHashValue (h, 1);
         4487  +        dk->unknownIDrefs--;
         4488  +        return 1;
         4489  +    } 
         4490  +    /* Duplicate ID value */
         4491  +    return 0;
         4492  +}
  4395   4493   
  4396   4494   static int
  4397   4495   idTCObjCmd (
  4398   4496       ClientData clientData,
  4399   4497       Tcl_Interp *interp,
  4400   4498       int objc,
  4401   4499       Tcl_Obj *const objv[]
  4402   4500       )
  4403   4501   {
  4404   4502       SchemaData *sdata = GETASI;
  4405   4503       SchemaConstraint *sc;
         4504  +    Tcl_HashEntry *h;
         4505  +    int hnew;
         4506  +    SchemaDocKey *dk;
  4406   4507   
  4407   4508       CHECK_TI
  4408   4509       CHECK_TOPLEVEL
  4409         -    checkNrArgs (1,1,"no argument expected");
         4510  +    checkNrArgs (1,2,"?key_space?");
  4410   4511       ADD_CONSTRAINT (sdata, sc)
  4411         -    sc->constraint = idImpl;
  4412         -    sc->constraintData = (void *)sdata;
         4512  +    if (objc == 1) {
         4513  +        sc->constraint = idImpl;
         4514  +        sc->constraintData = (void *)sdata;
         4515  +    } else {
         4516  +        h = Tcl_CreateHashEntry (&sdata->idTables, Tcl_GetString (objv[1]),
         4517  +                                 &hnew);
         4518  +        if (hnew) {
         4519  +            dk = TMALLOC (SchemaDocKey);
         4520  +            Tcl_InitHashTable (&dk->ids, TCL_STRING_KEYS);
         4521  +            dk->unknownIDrefs = 0;
         4522  +            Tcl_SetHashValue (h, dk);
         4523  +        } else {
         4524  +            dk = Tcl_GetHashValue (h);
         4525  +        }
         4526  +        sc->constraint = docidImpl;
         4527  +        sc->constraintData = (void *)dk;
         4528  +    }
  4413   4529       return TCL_OK;
  4414   4530   }
  4415   4531   
  4416   4532   static int
  4417   4533   idrefImpl (
  4418   4534       Tcl_Interp *interp,
  4419   4535       void *constraintData,
................................................................................
  4427   4543       h = Tcl_CreateHashEntry (&sdata->ids, text, &hnew);
  4428   4544       if (hnew) {
  4429   4545           Tcl_SetHashValue (h, 0);
  4430   4546           sdata->unknownIDrefs++;
  4431   4547       }
  4432   4548       return 1;
  4433   4549   }
         4550  +
         4551  +static int
         4552  +docidrefImpl (
         4553  +    Tcl_Interp *interp,
         4554  +    void *constraintData,
         4555  +    char *text
         4556  +    )
         4557  +{
         4558  +    SchemaDocKey *dk = (SchemaDocKey *) constraintData;
         4559  +    int hnew;
         4560  +    Tcl_HashEntry *h;
         4561  +
         4562  +    h = Tcl_CreateHashEntry (&dk->ids, text, &hnew);
         4563  +    if (hnew) {
         4564  +        Tcl_SetHashValue (h, 0);
         4565  +        dk->unknownIDrefs++;
         4566  +    }
         4567  +    return 1;
         4568  +}
  4434   4569   
  4435   4570   static int
  4436   4571   idrefTCObjCmd (
  4437   4572       ClientData clientData,
  4438   4573       Tcl_Interp *interp,
  4439   4574       int objc,
  4440   4575       Tcl_Obj *const objv[]
  4441   4576       )
  4442   4577   {
  4443   4578       SchemaData *sdata = GETASI;
  4444   4579       SchemaConstraint *sc;
         4580  +    Tcl_HashEntry *h;
         4581  +    int hnew;
         4582  +    SchemaDocKey *dk;
  4445   4583   
  4446   4584       CHECK_TI
  4447   4585       CHECK_TOPLEVEL
  4448         -    checkNrArgs (1,1,"no argument expected");
         4586  +    checkNrArgs (1,2,"?key_space?");
  4449   4587       ADD_CONSTRAINT (sdata, sc)
  4450         -    sc->constraint = idrefImpl;
  4451         -    sc->constraintData = (void *)sdata;
         4588  +    if (objc == 1) {
         4589  +        sc->constraint = idrefImpl;
         4590  +        sc->constraintData = (void *)sdata;
         4591  +    } else {
         4592  +        h = Tcl_CreateHashEntry (&sdata->idTables, Tcl_GetString (objv[1]),
         4593  +                                 &hnew);
         4594  +        if (hnew) {
         4595  +            dk = TMALLOC (SchemaDocKey);
         4596  +            Tcl_InitHashTable (&dk->ids, TCL_STRING_KEYS);
         4597  +            dk->unknownIDrefs = 0;
         4598  +            Tcl_SetHashValue (h, dk);
         4599  +        } else {
         4600  +            dk = Tcl_GetHashValue (h);
         4601  +        }
         4602  +        sc->constraint = docidrefImpl;
         4603  +        sc->constraintData = (void *)dk;
         4604  +    }
  4452   4605       return TCL_OK;
  4453   4606   }
  4454   4607   
  4455   4608   static int
  4456   4609   base64Impl (
  4457   4610       Tcl_Interp *interp,
  4458   4611       void *constraintData,

Changes to generic/schema.h.

   101    101       VALIDATION_READY,
   102    102       VALIDATION_STARTED,
   103    103       VALIDATION_ERROR,
   104    104       VALIDATION_FINISHED
   105    105   } ValidationState;
   106    106   
   107    107   typedef struct 
          108  +{
          109  +    Tcl_HashTable ids;
          110  +    int unknownIDrefs;
          111  +} SchemaDocKey;
          112  +    
          113  +typedef struct 
   108    114   {
   109    115       Tcl_Obj *self;
   110    116       char *start;
   111    117       char *startNamespace;
   112    118       Tcl_HashTable element;
   113    119       Tcl_HashTable namespace;
   114    120       Tcl_HashEntry *emptyNamespace;
................................................................................
   143    149       SchemaValidationStack *stack;
   144    150       SchemaValidationStack *stackPool;
   145    151       ValidationState validationState;
   146    152       unsigned int skipDeep;
   147    153       Tcl_DString *cdata;
   148    154       Tcl_HashTable ids;
   149    155       int unknownIDrefs;
          156  +    Tcl_HashTable idTables;
   150    157   } SchemaData;
   151    158   
   152    159   int 
   153    160   schemaInstanceCmd (
   154    161       ClientData clientData,
   155    162       Tcl_Interp *interp,
   156    163       int objc,

Changes to tests/schema.test.

  3796   3796           {<doc>===</doc>}        
  3797   3797       } {
  3798   3798           lappend result [s validate $xml]
  3799   3799       }
  3800   3800       s delete
  3801   3801       set result
  3802   3802   } {1 1 1 0 1 1 0 0}
         3803  +
         3804  +test schema-14.27 {element content id/idref} {
         3805  +    tdom::schema s
         3806  +    s define {
         3807  +        defelement doc {
         3808  +            interleave {
         3809  +                element id *
         3810  +                element idref *
         3811  +                element ida *
         3812  +                element idrefa *
         3813  +            }
         3814  +        }
         3815  +        defelement id {text id}
         3816  +        defelement idref {text idref}
         3817  +        defelement ida {text {id a}}
         3818  +        defelement idrefa {text {idref a}}
         3819  +    }
         3820  +    set result [list]
         3821  +    foreach xml {
         3822  +        <doc/>
         3823  +        <doc><id>abc</id><ida>abc</ida></doc>
         3824  +        <doc><idrefa>abc</idrefa></doc>
         3825  +        <doc><idrefa>abc</idrefa><idref>abc</idref></doc>
         3826  +        <doc><id>1</id><idrefa>abc</idrefa><idref>abc</idref><idrefa>foo</idrefa><idref>abc</idref></doc>
         3827  +        <doc><id>abc</id><idref>abc</idref><ida>abc</ida><idrefa>abc</idrefa></doc>
         3828  +        <doc><idref>abc</idref><id>abc</id><idrefa>abc</idrefa><ida>abc</ida></doc>
         3829  +    } {
         3830  +        lappend result [s validate $xml]
         3831  +    }
         3832  +    s delete
         3833  +    set result
         3834  +} {1 1 0 0 0 1 1}
         3835  +
         3836  +test schema-14.28 {element content id/idref} {
         3837  +    tdom::schema s
         3838  +    s define {
         3839  +        defelement doc {
         3840  +            interleave {
         3841  +                element id *
         3842  +                element idref *
         3843  +                element ida *
         3844  +                element idrefa *
         3845  +            }
         3846  +        }
         3847  +        defelement id {text {id b}}
         3848  +        defelement idref {text {idref b}}
         3849  +        defelement ida {text {id a}}
         3850  +        defelement idrefa {text {idref a}}
         3851  +    }
         3852  +    set result [list]
         3853  +    foreach xml {
         3854  +        <doc/>
         3855  +        <doc><id>abc</id><ida>abc</ida></doc>
         3856  +        <doc><idrefa>abc</idrefa></doc>
         3857  +        <doc><idrefa>abc</idrefa><idref>abc</idref></doc>
         3858  +        <doc><id>1</id><idrefa>abc</idrefa><idref>abc</idref><idrefa>foo</idrefa><idref>abc</idref></doc>
         3859  +        <doc><id>abc</id><idref>abc</idref><ida>abc</ida><idrefa>abc</idrefa></doc>
         3860  +        <doc><idref>abc</idref><id>abc</id><idrefa>abc</idrefa><ida>abc</ida></doc>
         3861  +    } {
         3862  +        lappend result [s validate $xml]
         3863  +    }
         3864  +    s delete
         3865  +    set result
         3866  +} {1 1 0 0 0 1 1}
  3803   3867   
  3804   3868   test schema-15.1 {constraint cmd tcl} {
  3805   3869       tdom::schema s
  3806   3870       s define {
  3807   3871           defelement a {
  3808   3872               tcl append ::schema-15.1
  3809   3873               element b