tDOM

Check-in [abc0715900]
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 unique schema contraint: the fields argument is now expected to be a proper tcl list with their elements as the field XPath expressions.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | localkey
Files: files | file ages | folders
SHA3-256: abc071590006ac7d3a123d52d415927a8dd892840bad181d4b9bb2c46cc796fd
User & Date: rolf 2019-05-15 00:16:58
Context
2019-05-16
22:25
Still working on digest local key constraint specification: Now support union "Path ( '|' Path )*" for selector and fields. Distinct between element and attribute selecting steps because of the distict spaces of the names. check-in: 69c262ef77 user: rolf tags: localkey
2019-05-15
00:16
Enhanced the unique schema contraint: the fields argument is now expected to be a proper tcl list with their elements as the field XPath expressions. check-in: abc0715900 user: rolf tags: localkey
2019-05-14
20:04
Merge from schema. check-in: dc36b35000 user: rolf tags: localkey
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to generic/schema.c.

   375    375   
   376    376   static void freeKeyConstraints (
   377    377       KeyConstraint *kc
   378    378       )
   379    379   {
   380    380       KeyConstraint *knext;
   381    381       KeyStep *step, *snext;
   382         -
          382  +    int i;
          383  +    
   383    384       while (kc) {
   384    385           knext = kc->next;
   385    386           if (kc->name) FREE (kc->name);
   386         -        step = kc->selectSteps;
          387  +        step = kc->selector;
   387    388           while (step) {
   388    389               snext = step->next;
   389    390               FREE (step);
   390    391               step = snext;
   391    392           }
   392         -        step = kc->fieldSteps;
   393         -        while (step) {
   394         -            snext = step->next;
   395         -            FREE (step);
   396         -            step = snext;
          393  +        for (i = 0; i < kc->nrFields; i++) {
          394  +            step = kc->fields[i];
          395  +            while (step) {
          396  +                snext = step->next;
          397  +                FREE (step);
          398  +                step = snext;
          399  +            }
   397    400           }
          401  +        FREE (kc->fields);
   398    402           FREE (kc);
   399    403           kc = knext;
   400    404       }
   401    405   }
   402    406   
   403    407   static void freeSchemaCP (
   404    408       SchemaCP *pattern
................................................................................
  3526   3530                   REMEMBER_PATTERN (cp);
  3527   3531                   Tcl_SetHashValue (h, cp);
  3528   3532               }
  3529   3533               step->name = Tcl_GetHashKey (&sdata->element, h);
  3530   3534               if (lastStep) {
  3531   3535                   lastStep->next = step;
  3532   3536               } else {
  3533         -                if (field) kc->fieldSteps = step;
  3534         -                else kc->selectSteps = step;
         3537  +                if (field) kc->fields[field-1] = step;
         3538  +                else kc->selector = step;
  3535   3539               }
  3536   3540               lastStep = step;
  3537   3541               t = savedt;
  3538   3542               break;
  3539   3543           case AxisChild:
  3540   3544               nextType = SCHEMA_STEP_ELEMENT;
  3541   3545               break;
................................................................................
  3562   3566       ClientData clientData,
  3563   3567       Tcl_Interp *interp,
  3564   3568       int objc,
  3565   3569       Tcl_Obj *const objv[]
  3566   3570       )
  3567   3571   {
  3568   3572       SchemaData *sdata = GETASI;
  3569         -    ast s, f;
         3573  +    ast t;
  3570   3574       char *errMsg = NULL;
  3571   3575       KeyConstraint *kc, *kc1;
         3576  +    int i, nrFields;
         3577  +    Tcl_Obj *elm;
  3572   3578   
  3573   3579       CHECK_SI
  3574   3580       CHECK_TOPLEVEL
  3575         -    checkNrArgs (3,3,"Expected: <selector> <fieldlist>");
  3576         -
         3581  +    checkNrArgs (3,4,"Expected: <selector> <fieldlist> ?<name>?");
         3582  +    if (sdata->cp->type != SCHEMA_CTYPE_NAME) {
         3583  +        SetResult ("The unique schema definition command is only "
         3584  +                   "allowed as direct child of an element.");
         3585  +    }
         3586  +    
  3577   3587       if (xpathParse (Tcl_GetString (objv[1]), NULL, XPATH_EXPR,
  3578         -                    sdata->prefixns, NULL, &s, &errMsg) < 0) {
         3588  +                    sdata->prefixns, NULL, &t, &errMsg) < 0) {
  3579   3589           SetResult3 ("Error in selector xpath: '", errMsg, "");
  3580   3590           FREE (errMsg);
  3581   3591           return TCL_ERROR;
  3582   3592       }
  3583         -    if (xpathParse (Tcl_GetString (objv[2]), NULL, XPATH_EXPR,
  3584         -                    sdata->prefixns, NULL, &f, &errMsg) < 0) {
  3585         -        SetResult3 ("Error in field xpath: '", errMsg, "");
  3586         -        FREE (errMsg);
         3593  +
         3594  +    if (Tcl_ListObjLength (interp, objv[2], &nrFields) != TCL_OK) {
         3595  +        SetResult ("The <fieldlist> argument must be a valid tcl list");
         3596  +        xpathFreeAst (t);
  3587   3597           return TCL_ERROR;
  3588   3598       }
         3599  +    
  3589   3600       kc = TMALLOC (KeyConstraint);
  3590   3601       memset (kc, 0, sizeof (KeyConstraint));
  3591         -    if (processSchemaXPath (interp, sdata, kc, NULL, SCHEMA_STEP_NONE, s, 0, 1)
         3602  +    kc->fields = MALLOC (sizeof (KeyStep*) * nrFields);
         3603  +
         3604  +    if (processSchemaXPath (interp, sdata, kc, NULL, SCHEMA_STEP_NONE, t, 0, 1)
  3592   3605           != TCL_OK) {
  3593         -        xpathFreeAst (s);
  3594         -        xpathFreeAst (f);
         3606  +        xpathFreeAst (t);
  3595   3607           freeKeyConstraints (kc);
  3596   3608           return TCL_ERROR;
  3597   3609       }
  3598         -    if (processSchemaXPath (interp, sdata, kc, NULL, SCHEMA_STEP_NONE, f, 1, 1)
  3599         -        != TCL_OK) {
  3600         -        xpathFreeAst (s);
  3601         -        xpathFreeAst (f);
  3602         -        freeKeyConstraints (kc);
  3603         -        return TCL_ERROR;
         3610  +    xpathFreeAst (t);
         3611  +
         3612  +    for (i = 0; i < nrFields; i++) {
         3613  +        Tcl_ListObjIndex (interp, objv[2], i, &elm);
         3614  +        if (xpathParse (Tcl_GetString (elm), NULL, XPATH_EXPR,
         3615  +                        sdata->prefixns, NULL, &t, &errMsg) < 0) {
         3616  +            SetResult3 ("Error in field xpath: '", errMsg, "");
         3617  +            FREE (errMsg);
         3618  +            xpathFreeAst (t);
         3619  +            freeKeyConstraints (kc);
         3620  +            return TCL_ERROR;
         3621  +        }
         3622  +        if (processSchemaXPath (interp, sdata, kc, NULL, SCHEMA_STEP_NONE, t, i+1, 1)
         3623  +            != TCL_OK) {
         3624  +            xpathFreeAst (t);
         3625  +            freeKeyConstraints (kc);
         3626  +            return TCL_ERROR;
         3627  +        }
         3628  +        xpathFreeAst (t);
  3604   3629       }
  3605         -    xpathFreeAst (s);
  3606         -    xpathFreeAst (f);
         3630  +    if (objc == 4) {
         3631  +        kc->name = tdomstrdup (Tcl_GetString (objv[3]));
         3632  +    }
  3607   3633       if (sdata->cp->localkeys) {
  3608   3634           kc1 = sdata->cp->localkeys;
  3609   3635           while (kc1->next) kc1 = kc1->next;
  3610   3636           kc1->next = kc;
  3611   3637       } else {
  3612   3638           sdata->cp->localkeys = kc;
  3613   3639       }

Changes to generic/schema.h.

    13     13   |   License for the specific language governing rights and limitations
    14     14   |   under the License.
    15     15   |
    16     16   |   Contributor(s):
    17     17   |
    18     18   |
    19     19   |   written by Rolf Ade
    20         -|   Nov, Dec 2018
           20  +|   2018-2019
    21     21   |
    22     22   \---------------------------------------------------------------------------*/
    23     23   
    24     24   #ifndef __SCHEMA_H__
    25     25   #define __SCHEMA_H__
    26     26   
    27     27   typedef enum {
................................................................................
    91     91       StepType type;
    92     92       char    *name;
    93     93       char    *ns;
    94     94       struct KeyStep *next;
    95     95   } KeyStep;
    96     96   
    97     97   typedef struct KeyConstraint {
    98         -    char    *name;
    99         -    KeyType  type;
   100         -    KeyStep *selectSteps;
   101         -    KeyStep *fieldSteps;
           98  +    char     *name;
           99  +    KeyType   type;
          100  +    KeyStep  *selector;
          101  +    KeyStep  **fields;
          102  +    int       nrFields;
   102    103       struct KeyConstraint *next;
   103    104   } KeyConstraint;
   104    105   
   105    106   typedef struct SchemaCP
   106    107   {
   107    108       Schema_CP_Type    type;
   108    109       char             *namespace;

Changes to tests/schema.test.

  4672   4672           //a
  4673   4673           a/@ref
  4674   4674           a/b/c
  4675   4675           a//b/c
  4676   4676           (.//b|a)/c
  4677   4677           ns1:a
  4678   4678           a/.//b/c
         4679  +        {}
         4680  +        {    }
         4681  +        "
         4682  +                "
  4679   4683       } {
  4680   4684           tdom::schema s
  4681   4685           lappend result [catch {s define $schema} errMsg]
  4682   4686           #puts $errMsg
  4683   4687           s delete
  4684   4688       }
  4685   4689       set result
  4686         -} {0 1 1 0 1 1 1 1 0 1 1 0 1 1 0 1}
         4690  +} {0 1 1 0 1 1 1 1 0 1 1 0 1 1 0 1 1 1 1}
         4691  +
         4692  +test schema-19.3 {unique} {
         4693  +    tdom::schema s
         4694  +    s define {
         4695  +        defelement doc {
         4696  +            unique item @lang
         4697  +            element item * {
         4698  +                attribute lang
         4699  +            }
         4700  +        }
         4701  +    }
         4702  +    set result [list]
         4703  +    foreach xml {
         4704  +        {<doc><item lang="de"/><item lang="en"/><item lang="fr"/></doc>}
         4705  +    } {
         4706  +        lappend result [s validate $xml]
         4707  +    }
         4708  +    s delete
         4709  +    set result
         4710  +} {1}
         4711  +
         4712  +test schema-19.4 {unique} {
         4713  +    tdom::schema s
         4714  +    s define {
         4715  +        defelement doc {
         4716  +            unique item {@lang @sub} "Combined field unique constraint"
         4717  +            element item * {
         4718  +                attribute lang
         4719  +            }
         4720  +        }
         4721  +    }
         4722  +    set result [list]
         4723  +    foreach xml {
         4724  +        {<doc><item lang="de"/><item lang="en"/><item lang="fr"/></doc>}
         4725  +    } {
         4726  +        lappend result [s validate $xml]
         4727  +    }
         4728  +    s delete
         4729  +    set result
         4730  +} {1}
  4687   4731   
  4688   4732   }