tDOM

Check-in [abc0715900]
Login

Check-in [abc0715900]

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
Timelines: family | ancestors | descendants | both | localkey
Files: files | file ages | folders
SHA3-256: abc071590006ac7d3a123d52d415927a8dd892840bad181d4b9bb2c46cc796fd
User & Date: rolf 2019-05-15 00:16:58.616
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
Unified Diff Ignore Whitespace Patch
Changes to generic/schema.c.
375
376
377
378
379
380
381

382
383
384
385
386
387
388
389
390
391

392
393
394
395
396
397


398
399
400
401
402
403
404

static void freeKeyConstraints (
    KeyConstraint *kc
    )
{
    KeyConstraint *knext;
    KeyStep *step, *snext;


    while (kc) {
        knext = kc->next;
        if (kc->name) FREE (kc->name);
        step = kc->selectSteps;
        while (step) {
            snext = step->next;
            FREE (step);
            step = snext;
        }

        step = kc->fieldSteps;
        while (step) {
            snext = step->next;
            FREE (step);
            step = snext;
        }


        FREE (kc);
        kc = knext;
    }
}

static void freeSchemaCP (
    SchemaCP *pattern







>
|



|





>
|
|
|
|
|
|
>
>







375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408

static void freeKeyConstraints (
    KeyConstraint *kc
    )
{
    KeyConstraint *knext;
    KeyStep *step, *snext;
    int i;
    
    while (kc) {
        knext = kc->next;
        if (kc->name) FREE (kc->name);
        step = kc->selector;
        while (step) {
            snext = step->next;
            FREE (step);
            step = snext;
        }
        for (i = 0; i < kc->nrFields; i++) {
            step = kc->fields[i];
            while (step) {
                snext = step->next;
                FREE (step);
                step = snext;
            }
        }
        FREE (kc->fields);
        FREE (kc);
        kc = knext;
    }
}

static void freeSchemaCP (
    SchemaCP *pattern
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
                REMEMBER_PATTERN (cp);
                Tcl_SetHashValue (h, cp);
            }
            step->name = Tcl_GetHashKey (&sdata->element, h);
            if (lastStep) {
                lastStep->next = step;
            } else {
                if (field) kc->fieldSteps = step;
                else kc->selectSteps = step;
            }
            lastStep = step;
            t = savedt;
            break;
        case AxisChild:
            nextType = SCHEMA_STEP_ELEMENT;
            break;







|
|







3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
                REMEMBER_PATTERN (cp);
                Tcl_SetHashValue (h, cp);
            }
            step->name = Tcl_GetHashKey (&sdata->element, h);
            if (lastStep) {
                lastStep->next = step;
            } else {
                if (field) kc->fields[field-1] = step;
                else kc->selector = step;
            }
            lastStep = step;
            t = savedt;
            break;
        case AxisChild:
            nextType = SCHEMA_STEP_ELEMENT;
            break;
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571


3572
3573
3574
3575



3576

3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588

3589
3590


3591
3592
3593



3594








3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605

3606


3607
3608
3609
3610
3611
3612
3613
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[]
    )
{
    SchemaData *sdata = GETASI;
    ast s, f;
    char *errMsg = NULL;
    KeyConstraint *kc, *kc1;



    CHECK_SI
    CHECK_TOPLEVEL
    checkNrArgs (3,3,"Expected: <selector> <fieldlist>");





    if (xpathParse (Tcl_GetString (objv[1]), NULL, XPATH_EXPR,
                    sdata->prefixns, NULL, &s, &errMsg) < 0) {
        SetResult3 ("Error in selector xpath: '", errMsg, "");
        FREE (errMsg);
        return TCL_ERROR;
    }
    if (xpathParse (Tcl_GetString (objv[2]), NULL, XPATH_EXPR,
                    sdata->prefixns, NULL, &f, &errMsg) < 0) {
        SetResult3 ("Error in field xpath: '", errMsg, "");
        FREE (errMsg);
        return TCL_ERROR;
    }

    kc = TMALLOC (KeyConstraint);
    memset (kc, 0, sizeof (KeyConstraint));


    if (processSchemaXPath (interp, sdata, kc, NULL, SCHEMA_STEP_NONE, s, 0, 1)
        != TCL_OK) {
        xpathFreeAst (s);



        xpathFreeAst (f);








        freeKeyConstraints (kc);
        return TCL_ERROR;
    }
    if (processSchemaXPath (interp, sdata, kc, NULL, SCHEMA_STEP_NONE, f, 1, 1)
        != TCL_OK) {
        xpathFreeAst (s);
        xpathFreeAst (f);
        freeKeyConstraints (kc);
        return TCL_ERROR;
    }
    xpathFreeAst (s);

    xpathFreeAst (f);


    if (sdata->cp->localkeys) {
        kc1 = sdata->cp->localkeys;
        while (kc1->next) kc1 = kc1->next;
        kc1->next = kc;
    } else {
        sdata->cp->localkeys = kc;
    }







|


>
>



|
>
>
>
|
>

|




|
|
|
|


>


>
>
|

|
>
>
>
|
>
>
>
>
>
>
>
>
|
|
|
|
|
|
<
|
|
|
|
>
|
>
>







3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624

3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[]
    )
{
    SchemaData *sdata = GETASI;
    ast t;
    char *errMsg = NULL;
    KeyConstraint *kc, *kc1;
    int i, nrFields;
    Tcl_Obj *elm;

    CHECK_SI
    CHECK_TOPLEVEL
    checkNrArgs (3,4,"Expected: <selector> <fieldlist> ?<name>?");
    if (sdata->cp->type != SCHEMA_CTYPE_NAME) {
        SetResult ("The unique schema definition command is only "
                   "allowed as direct child of an element.");
    }
    
    if (xpathParse (Tcl_GetString (objv[1]), NULL, XPATH_EXPR,
                    sdata->prefixns, NULL, &t, &errMsg) < 0) {
        SetResult3 ("Error in selector xpath: '", errMsg, "");
        FREE (errMsg);
        return TCL_ERROR;
    }

    if (Tcl_ListObjLength (interp, objv[2], &nrFields) != TCL_OK) {
        SetResult ("The <fieldlist> argument must be a valid tcl list");
        xpathFreeAst (t);
        return TCL_ERROR;
    }
    
    kc = TMALLOC (KeyConstraint);
    memset (kc, 0, sizeof (KeyConstraint));
    kc->fields = MALLOC (sizeof (KeyStep*) * nrFields);

    if (processSchemaXPath (interp, sdata, kc, NULL, SCHEMA_STEP_NONE, t, 0, 1)
        != TCL_OK) {
        xpathFreeAst (t);
        freeKeyConstraints (kc);
        return TCL_ERROR;
    }
    xpathFreeAst (t);

    for (i = 0; i < nrFields; i++) {
        Tcl_ListObjIndex (interp, objv[2], i, &elm);
        if (xpathParse (Tcl_GetString (elm), NULL, XPATH_EXPR,
                        sdata->prefixns, NULL, &t, &errMsg) < 0) {
            SetResult3 ("Error in field xpath: '", errMsg, "");
            FREE (errMsg);
            xpathFreeAst (t);
            freeKeyConstraints (kc);
            return TCL_ERROR;
        }
        if (processSchemaXPath (interp, sdata, kc, NULL, SCHEMA_STEP_NONE, t, i+1, 1)
            != TCL_OK) {
            xpathFreeAst (t);

            freeKeyConstraints (kc);
            return TCL_ERROR;
        }
        xpathFreeAst (t);
    }
    if (objc == 4) {
        kc->name = tdomstrdup (Tcl_GetString (objv[3]));
    }
    if (sdata->cp->localkeys) {
        kc1 = sdata->cp->localkeys;
        while (kc1->next) kc1 = kc1->next;
        kc1->next = kc;
    } else {
        sdata->cp->localkeys = kc;
    }
Changes to generic/schema.h.
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|   License for the specific language governing rights and limitations
|   under the License.
|
|   Contributor(s):
|
|
|   written by Rolf Ade
|   Nov, Dec 2018
|
\---------------------------------------------------------------------------*/

#ifndef __SCHEMA_H__
#define __SCHEMA_H__

typedef enum {







|







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|   License for the specific language governing rights and limitations
|   under the License.
|
|   Contributor(s):
|
|
|   written by Rolf Ade
|   2018-2019
|
\---------------------------------------------------------------------------*/

#ifndef __SCHEMA_H__
#define __SCHEMA_H__

typedef enum {
91
92
93
94
95
96
97
98
99
100
101

102
103
104
105
106
107
108
    StepType type;
    char    *name;
    char    *ns;
    struct KeyStep *next;
} KeyStep;

typedef struct KeyConstraint {
    char    *name;
    KeyType  type;
    KeyStep *selectSteps;
    KeyStep *fieldSteps;

    struct KeyConstraint *next;
} KeyConstraint;

typedef struct SchemaCP
{
    Schema_CP_Type    type;
    char             *namespace;







|
|
|
|
>







91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
    StepType type;
    char    *name;
    char    *ns;
    struct KeyStep *next;
} KeyStep;

typedef struct KeyConstraint {
    char     *name;
    KeyType   type;
    KeyStep  *selector;
    KeyStep  **fields;
    int       nrFields;
    struct KeyConstraint *next;
} KeyConstraint;

typedef struct SchemaCP
{
    Schema_CP_Type    type;
    char             *namespace;
Changes to tests/schema.test.
4672
4673
4674
4675
4676
4677
4678




4679
4680
4681
4682
4683
4684
4685
4686








































4687
4688
        //a
        a/@ref
        a/b/c
        a//b/c
        (.//b|a)/c
        ns1:a
        a/.//b/c




    } {
        tdom::schema s
        lappend result [catch {s define $schema} errMsg]
        #puts $errMsg
        s delete
    }
    set result
} {0 1 1 0 1 1 1 1 0 1 1 0 1 1 0 1}









































}







>
>
>
>







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


4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
        //a
        a/@ref
        a/b/c
        a//b/c
        (.//b|a)/c
        ns1:a
        a/.//b/c
        {}
        {    }
        "
                "
    } {
        tdom::schema s
        lappend result [catch {s define $schema} errMsg]
        #puts $errMsg
        s delete
    }
    set result
} {0 1 1 0 1 1 1 1 0 1 1 0 1 1 0 1 1 1 1}

test schema-19.3 {unique} {
    tdom::schema s
    s define {
        defelement doc {
            unique item @lang
            element item * {
                attribute lang
            }
        }
    }
    set result [list]
    foreach xml {
        {<doc><item lang="de"/><item lang="en"/><item lang="fr"/></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1}

test schema-19.4 {unique} {
    tdom::schema s
    s define {
        defelement doc {
            unique item {@lang @sub} "Combined field unique constraint"
            element item * {
                attribute lang
            }
        }
    }
    set result [list]
    foreach xml {
        {<doc><item lang="de"/><item lang="en"/><item lang="fr"/></doc>}
    } {
        lappend result [s validate $xml]
    }
    s delete
    set result
} {1}

}