Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch localkey Excluding Merge-Ins
This is equivalent to a diff from ba6bd2bb7c to 66e05a9e1a
2019-05-31
| ||
00:05 | Added sub tree local uniqueness and foreign key contents. check-in: 43cf45b772 user: rolf tags: schema | |
2019-05-25
| ||
00:46 | Started work. (Wenn es anders nicht geht, so geht es doch viel besser.) check-in: 11c1cd9dad user: rolf tags: keyspaces | |
2019-05-24
| ||
12:54 | Save work. Closed-Leaf check-in: 66e05a9e1a user: rolf tags: localkey | |
2019-05-22
| ||
22:22 | Added the XPath step "." as allowed step in restricted schema XPath Expressions. check-in: ab18265ee0 user: rolf tags: localkey | |
2019-05-21
| ||
22:37 | Merged from schema. check-in: 72ce7820c1 user: rolf tags: localkey | |
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 | |
22:24 | Added optional flag argument to domunique. Currently only flag controls, if empty field node sets are ignored (or seen as the empty string). Closed-Leaf check-in: 6a51d9897b user: rolf tags: domlocalkey | |
2019-05-14
| ||
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 | |
Changes to generic/dom.c.
︙ | ︙ | |||
648 649 650 651 652 653 654 | while (prefixMappings[i]) { if (strcmp (prefix, prefixMappings[i]) == 0) { return prefixMappings[i+1]; } i += 2; } } | > | | > | | 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 | while (prefixMappings[i]) { if (strcmp (prefix, prefixMappings[i]) == 0) { return prefixMappings[i+1]; } i += 2; } } if (node) { ns = domLookupPrefix (node, prefix); if (ns) return ns->uri; } return NULL; } /*--------------------------------------------------------------------------- | domLookupPrefix | \--------------------------------------------------------------------------*/ domNS * |
︙ | ︙ |
Changes to generic/schema.c.
︙ | ︙ | |||
262 263 264 265 266 267 268 269 270 271 272 273 274 275 | if (cp->namespace) { \ Tcl_SetStringObj (rObj, cp->namespace, -1); \ Tcl_AppendToObj (rObj, ":", 1); \ } \ Tcl_AppendToObj (rObj, cp->name, -1); #define S(str) str, sizeof (str) -1 static SchemaCP* initSchemaCP ( Schema_CP_Type type, void *namespace, char *name ) | > > > > > > > > | 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 | if (cp->namespace) { \ Tcl_SetStringObj (rObj, cp->namespace, -1); \ Tcl_AppendToObj (rObj, ":", 1); \ } \ Tcl_AppendToObj (rObj, cp->name, -1); #define S(str) str, sizeof (str) -1 #define getKeyState(ks) \ if (sdata->keyStatePool) { \ ks = sdata->keyStatePool; \ sdata->keyStatePool = ks->next; \ } else { \ ks = TMALLOC (KeyState); \ } static SchemaCP* initSchemaCP ( Schema_CP_Type type, void *namespace, char *name ) |
︙ | ︙ | |||
376 377 378 379 380 381 382 383 384 385 386 387 388 389 | } fprintf (stderr, "++++ Stack bottom\n"); } ) /* DBG end */ static void freedomKeyConstraints ( domKeyConstraint *kc ) { domKeyConstraint *knext; int i; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 | } fprintf (stderr, "++++ Stack bottom\n"); } ) /* DBG end */ static void freeKeyConstraints ( KeyConstraint *kc ) { KeyConstraint *knext; KeyStep *step, *snext, *child, *nchild; int i; while (kc) { knext = kc->next; if (kc->name) FREE (kc->name); step = kc->selector; while (step) { snext = step->next; child = step; while (child) { nchild = child->child; FREE (child); child = nchild; } step = snext; } for (i = 0; i < kc->nrFields; i++) { step = kc->fields[i]; while (step) { snext = step->next; child = step; while (child) { nchild = child->child; FREE (child); child = nchild; } step = snext; } } FREE (kc->fields); FREE (kc); kc = knext; } } static void freedomKeyConstraints ( domKeyConstraint *kc ) { domKeyConstraint *knext; int i; |
︙ | ︙ | |||
432 433 434 435 436 437 438 439 440 441 442 443 444 445 | FREE (pattern->quants); if (pattern->attrs) { for (i = 0; i < pattern->numAttr; i++) { FREE (pattern->attrs[i]); } FREE (pattern->attrs); } freedomKeyConstraints (pattern->domKeys); break; } FREE (pattern); } static SchemaData* | > | 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 | FREE (pattern->quants); if (pattern->attrs) { for (i = 0; i < pattern->numAttr; i++) { FREE (pattern->attrs[i]); } FREE (pattern->attrs); } freeKeyConstraints (pattern->localkeys); freedomKeyConstraints (pattern->domKeys); break; } FREE (pattern); } static SchemaData* |
︙ | ︙ | |||
499 500 501 502 503 504 505 506 507 508 509 510 511 512 | { SchemaData *sdata = (SchemaData *) clientData; unsigned int i; SchemaValidationStack *down; Tcl_HashEntry *h; Tcl_HashSearch search; SchemaDocKey *dk; /* Protect the clientData to be freed inside (even nested) * Tcl_Eval*() calls to avoid invalid mem access and postpone the * cleanup until the Tcl_Eval*() calls are finished (done in * schemaInstanceCmd(). */ if (sdata->currentEvals) { sdata->cleanupAfterEval = 1; | > > | 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 | { SchemaData *sdata = (SchemaData *) clientData; unsigned int i; SchemaValidationStack *down; Tcl_HashEntry *h; Tcl_HashSearch search; SchemaDocKey *dk; KeyState *ks, *nextks; KeyTable *kt, *nextkt; /* Protect the clientData to be freed inside (even nested) * Tcl_Eval*() calls to avoid invalid mem access and postpone the * cleanup until the Tcl_Eval*() calls are finished (done in * schemaInstanceCmd(). */ if (sdata->currentEvals) { sdata->cleanupAfterEval = 1; |
︙ | ︙ | |||
564 565 566 567 568 569 570 571 572 573 574 575 576 577 | h != NULL; h = Tcl_NextHashEntry (&search)) { dk = Tcl_GetHashValue (h); Tcl_DeleteHashTable (&dk->ids); FREE (dk); } Tcl_DeleteHashTable (&sdata->idTables); FREE (sdata); } static void cleanupLastPattern ( SchemaData *sdata, unsigned int from | > > > > > > > > > > > > | 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 | h != NULL; h = Tcl_NextHashEntry (&search)) { dk = Tcl_GetHashValue (h); Tcl_DeleteHashTable (&dk->ids); FREE (dk); } Tcl_DeleteHashTable (&sdata->idTables); ks = sdata->keyStatePool; while (ks) { nextks = ks->next; FREE (ks); ks = nextks; } kt = sdata->keyTablePool; while (kt) { nextkt = kt->next; FREE (kt); kt = nextkt; } FREE (sdata); } static void cleanupLastPattern ( SchemaData *sdata, unsigned int from |
︙ | ︙ | |||
720 721 722 723 724 725 726 | static void pushToStack ( SchemaData *sdata, SchemaCP *pattern ) { SchemaValidationStack *stackElm, *se; | > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 | static void pushToStack ( SchemaData *sdata, SchemaCP *pattern ) { SchemaValidationStack *stackElm, *se; KeyConstraint *kc; KeyState *ks, *newks; KeyTable *kt; DBG(fprintf(stderr, "push to Stack:\n");serializeCP(pattern)); if (sdata->stackPool) { stackElm = sdata->stackPool; sdata->stackPool = stackElm->down; } else { stackElm = TMALLOC (SchemaValidationStack); } memset (stackElm, 0, sizeof (SchemaValidationStack)); se = sdata->stack; stackElm->down = se; stackElm->pattern = pattern; if (pattern->type == SCHEMA_CTYPE_INTERLEAVE) { stackElm->interleaveState = MALLOC (sizeof (int) * pattern->nc); memset (stackElm->interleaveState, 0, sizeof (int) * pattern->nc); } if (pattern->type == SCHEMA_CTYPE_NAME && se) { /* Handle local key contraint matches */ ks = se->keyState; while (ks) { if (ks->selector->name != pattern->name || ks->selector->ns != pattern->namespace) { ks = ks->next; continue; } if (ks->selector->child) { getKeyState(newks); newks->keyTable = ks->keyTable; newks->ownTable = 0; newks->selector = ks->selector->child; newks->fields = ks->fields; newks->next = stackElm->keyState; stackElm->keyState = newks; if (ks->type == SCHEMA_STEP_DESCENDANT_ELEMENT) { getKeyState(newks); newks->keyTable = ks->keyTable; newks->ownTable = 0; newks->selector = ks->selector; newks->fields = ks->fields; newks->next = stackElm->keyState; stackElm->keyState = newks; } } else { /* Selector has matched, grab the fields */ } } /* And open new local key contraints, if necessary. */ kc = pattern->localkeys; while (kc) { getKeyState (ks); if (sdata->keyTablePool) { kt = sdata->keyTablePool; sdata->keyTablePool = kt->next; } else { kt = TMALLOC (KeyTable); } Tcl_InitHashTable (&kt->values, TCL_STRING_KEYS); ks->keyTable = kt; ks->ownTable = 1; ks->type = kc->type; ks->selector = kc->selector; ks->fields = kc->fields; ks->next = stackElm->keyState; stackElm->keyState = ks; kc = kc->next; } } sdata->stack = stackElm; } static void popStack ( SchemaData *sdata ) { SchemaValidationStack *se; KeyState *ks, *nextks; DBG(fprintf(stderr, "pop from Stack:\n");serializeCP(sdata->stack->pattern)); if (sdata->stack->interleaveState) { FREE (sdata->stack->interleaveState); sdata->stack->interleaveState = NULL; } if (sdata->stack->pattern->type == SCHEMA_CTYPE_NAME) { /* Check and cleanup local key contraints */ ks = sdata->stack->keyState; while (ks) { nextks = ks->next; if (ks->ownTable) { ks->keyTable->next = sdata->keyTablePool; sdata->keyTablePool = ks->keyTable; Tcl_DeleteHashTable (&ks->keyTable->values); } ks->next = sdata->keyStatePool; sdata->keyStatePool = ks; ks = nextks; } } se = sdata->stack->down; sdata->stack->down = sdata->stackPool; sdata->stackPool = sdata->stack; sdata->stack = se; } |
︙ | ︙ | |||
3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 | pattern->content[i-1] = (SchemaCP *) objv[i]; Tcl_IncrRefCount (objv[i]); } pattern->nc = objc; addToContent (sdata, pattern, SCHEMA_CQUANT_ONE, 0, 0); return TCL_OK; } static int domuniquePatternCmd ( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 | pattern->content[i-1] = (SchemaCP *) objv[i]; Tcl_IncrRefCount (objv[i]); } pattern->nc = objc; addToContent (sdata, pattern, SCHEMA_CQUANT_ONE, 0, 0); return TCL_OK; } extern void printAst (int depth, ast t); static int processSchemaXPath ( Tcl_Interp *interp, SchemaData *sdata, KeyConstraint *kc, StepType nextType, ast t, int field, int toplevel ) { ast child, savedt; KeyStep *step, *curstep; Tcl_HashTable *table; Tcl_HashEntry *h; int rc, hnew; SchemaCP *cp; /* if (toplevel) printAst (0, t); */ while (t) { switch (t->type) { case GetContextNode: t = t->next; continue; case CombineSets: child = t->child; if (child->type == EvalSteps) { savedt = NULL; child = child->child; } else { savedt = child->next; child->next = NULL; } if (field) { step = kc->fields[field-1]; kc->fields[field-1] = NULL; } else { step = kc->selector; kc->selector = NULL; } if (!processSchemaXPath (interp, sdata, kc, SCHEMA_STEP_NONE, child, field, toplevel)) { if (savedt) child->next = savedt; if (field) kc->fields[field-1] = step; else kc->selector = step; return 0; } if (step) { if (field) { curstep = step; while (curstep->next) curstep = curstep->next; curstep->next = kc->fields[field-1]; } else { curstep = step; while (curstep->next) curstep = curstep->next; step->next = kc->selector; } } else { if (field) { step = kc->fields[field-1]; } else { step = kc->selector; } } if (field) kc->fields[field-1] = NULL; else kc->selector = NULL; if (savedt) child->next = savedt; child = t->child->next; if (child->type == EvalSteps) child = child->child; rc = processSchemaXPath (interp, sdata, kc, SCHEMA_STEP_NONE, child, field, toplevel); if (field) { if (kc->fields[field-1]) { curstep = step; while (curstep->next) curstep = curstep->next; curstep->next = kc->fields[field-1]; } kc->fields[field-1] = step; } else { if (kc->selector) { curstep = step; while (curstep->next) curstep = curstep->next; curstep->next = kc->selector; } kc->selector = step; } return rc; case AxisDescendant: if (!toplevel) { SetResult ("Not a reduced XPath expression."); return 0; } nextType = SCHEMA_STEP_DESCENDANT_ELEMENT; break; case IsNSAttr: case IsAttr: if (!field) { SetResult ("Attribute selection is only possible in reduced " "XPath expression for field selectors."); return 0; } /* Fall through */ case IsElement: case IsFQElement: case IsNSElement: savedt = t; step = TMALLOC (KeyStep); memset (step, 0, sizeof (KeyStep)); step->type = nextType; if (t->type == IsAttr || t->type == IsNSAttr) { table = &sdata->attrNames; } else { table = &sdata->element; } if (t->type == IsFQElement || t->type == IsNSAttr) { h = Tcl_CreateHashEntry (&sdata->namespace, t->strvalue, &hnew); step->ns = Tcl_GetHashKey (&sdata->namespace, h); t = t->child; } h = Tcl_CreateHashEntry (table, t->strvalue, &hnew); if (hnew && (table == &sdata->element)) { cp = initSchemaCP (SCHEMA_CTYPE_NAME, step->ns, Tcl_GetHashKey (&sdata->element, h)); cp->flags |= PLACEHOLDER_PATTERN_DEF; REMEMBER_PATTERN (cp); Tcl_SetHashValue (h, cp); } step->name = Tcl_GetHashKey (table, h); if (field) { if (kc->fields[field-1]) { curstep = kc->fields[field-1]; while (curstep->child) curstep = curstep->child; curstep->child = step; } else { kc->fields[field-1] = step; } } else { if (kc->selector) { curstep = kc->selector; while (curstep->child) curstep = curstep->child; curstep->child = step; } else { kc->selector = step; } } t = savedt; break; case AxisAttribute: if (!field) { SetResult ("Attribute selection is only possible in reduced " "XPath expression for field selectors."); return 0; } /* Fall through */ case AxisChild: if (t->type == AxisChild) nextType = SCHEMA_STEP_ELEMENT; else nextType = SCHEMA_STEP_ATTRIBUTE; if (!processSchemaXPath (interp, sdata, kc, nextType, t->child, field, 0)) { return 0; } break; default: SetResult ("Not a reduced XPath expression."); return 0; } toplevel = 0; t = t->next; } return 1; } static int uniquePatternCmd ( 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; } if (nrFields == 0) { SetResult ("Non empty fieldlist arugment expected."); xpathFreeAst (t); return TCL_ERROR; } kc = TMALLOC (KeyConstraint); memset (kc, 0, sizeof (KeyConstraint)); kc->fields = MALLOC (sizeof (KeyStep*) * nrFields); memset (kc->fields, 0, sizeof (KeyStep*) * nrFields); kc->nrFields = nrFields; if (!processSchemaXPath (interp, sdata, kc, SCHEMA_STEP_NONE, t, 0, 1)) { 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, SCHEMA_STEP_NONE, t, i+1, 1)) { 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; } return TCL_OK; } static int domuniquePatternCmd ( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] |
︙ | ︙ | |||
5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 | Tcl_CreateObjCommand (interp, "tdom::schema::text", TextPatternObjCmd, NULL, NULL); /* The 'virtual' "tcl" definition command */ Tcl_CreateObjCommand (interp, "tdom::schema::tcl", VirtualPatternObjCmd, NULL, NULL); /* XPath contraints for DOM validation */ Tcl_CreateObjCommand (interp,"tdom::schema::domunique", domuniquePatternCmd, NULL, NULL); /* The text constraint commands */ Tcl_CreateObjCommand (interp,"tdom::schema::text::integer", integerTCObjCmd, NULL, NULL); | > > > | 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 | Tcl_CreateObjCommand (interp, "tdom::schema::text", TextPatternObjCmd, NULL, NULL); /* The 'virtual' "tcl" definition command */ Tcl_CreateObjCommand (interp, "tdom::schema::tcl", VirtualPatternObjCmd, NULL, NULL); /* Identity definition commands */ Tcl_CreateObjCommand (interp,"tdom::schema::unique", uniquePatternCmd, NULL, NULL); /* XPath contraints for DOM validation */ Tcl_CreateObjCommand (interp,"tdom::schema::domunique", domuniquePatternCmd, NULL, NULL); /* The text constraint commands */ Tcl_CreateObjCommand (interp,"tdom::schema::text::integer", integerTCObjCmd, NULL, NULL); |
︙ | ︙ |
Changes to generic/schema.h.
︙ | ︙ | |||
13 14 15 16 17 18 19 | | License for the specific language governing rights and limitations | under the License. | | Contributor(s): | | | written by Rolf Ade | | | 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__ #include <tcldom.h> |
︙ | ︙ | |||
39 40 41 42 43 44 45 | typedef enum { SCHEMA_CQUANT_ONE, SCHEMA_CQUANT_OPT, SCHEMA_CQUANT_REP, SCHEMA_CQUANT_PLUS, SCHEMA_CQUANT_NM, | | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | typedef enum { SCHEMA_CQUANT_ONE, SCHEMA_CQUANT_OPT, SCHEMA_CQUANT_REP, SCHEMA_CQUANT_PLUS, SCHEMA_CQUANT_NM, SCHEMA_CQUANT_ERROR } SchemaQuant; typedef int (*SchemaConstraintFunc) (Tcl_Interp *interp, void *constraintData, char *text); typedef void (*SchemaConstraintFreeFunc) (void *constraintData); typedef struct |
︙ | ︙ | |||
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | ast selector; ast *fields; int nrFields; int flags; struct domKeyConstraint *next; } domKeyConstraint; typedef struct SchemaCP { Schema_CP_Type type; char *namespace; char *name; struct SchemaCP *next; SchemaFlags flags; struct SchemaCP **content; SchemaQuant *quants; unsigned int nc; SchemaAttr **attrs; unsigned int numAttr; unsigned int numReqAttr; domKeyConstraint *domKeys; } SchemaCP; typedef struct SchemaValidationStack { SchemaCP *pattern; struct SchemaValidationStack *next; struct SchemaValidationStack *down; int activeChild; int hasMatched; int *interleaveState; } SchemaValidationStack; typedef enum { VALIDATION_READY, VALIDATION_STARTED, VALIDATION_ERROR, VALIDATION_FINISHED | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | ast selector; ast *fields; int nrFields; int flags; struct domKeyConstraint *next; } domKeyConstraint; typedef enum { SCHEMA_KEY_UNIQUE, SCHEMA_KEY_KEY, SCHEMA_KEY_KEYREF } KeyType; typedef enum { SCHEMA_STEP_NONE, SCHEMA_STEP_ELEMENT, SCHEMA_STEP_DESCENDANT_ELEMENT, SCHEMA_STEP_ATTRIBUTE, SCHEMA_STEP_WILDCARD, SCHEMA_STEP_NSWILDCARD, } StepType; typedef struct KeyStep { StepType type; char *name; char *ns; struct KeyStep *next; struct KeyStep *child; } KeyStep; typedef struct KeyConstraint { char *name; KeyType type; KeyStep *selector; KeyStep **fields; int nrFields; struct KeyConstraint *next; } KeyConstraint; typedef struct KeyTable { struct KeyTable *next; Tcl_HashTable values; } KeyTable; typedef struct KeyState { struct KeyState *next; StepType type; KeyStep *selector; KeyStep **fields; int ownTable; KeyTable *keyTable; } KeyState; typedef struct SchemaCP { Schema_CP_Type type; char *namespace; char *name; struct SchemaCP *next; SchemaFlags flags; struct SchemaCP **content; SchemaQuant *quants; unsigned int nc; SchemaAttr **attrs; unsigned int numAttr; unsigned int numReqAttr; KeyConstraint *localkeys; domKeyConstraint *domKeys; } SchemaCP; typedef struct SchemaValidationStack { SchemaCP *pattern; struct SchemaValidationStack *next; struct SchemaValidationStack *down; int activeChild; int hasMatched; int *interleaveState; KeyState *keyState; } SchemaValidationStack; typedef enum { VALIDATION_READY, VALIDATION_STARTED, VALIDATION_ERROR, VALIDATION_FINISHED |
︙ | ︙ | |||
157 158 159 160 161 162 163 164 165 166 167 168 169 170 | unsigned int contentSize; SchemaAttr **currentAttrs; unsigned int numAttr; unsigned int numReqAttr; unsigned int attrSize; SchemaValidationStack *stack; SchemaValidationStack *stackPool; ValidationState validationState; unsigned int skipDeep; Tcl_DString *cdata; Tcl_HashTable ids; int unknownIDrefs; Tcl_HashTable idTables; } SchemaData; | > > | 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 | unsigned int contentSize; SchemaAttr **currentAttrs; unsigned int numAttr; unsigned int numReqAttr; unsigned int attrSize; SchemaValidationStack *stack; SchemaValidationStack *stackPool; KeyState *keyStatePool; KeyTable *keyTablePool; ValidationState validationState; unsigned int skipDeep; Tcl_DString *cdata; Tcl_HashTable ids; int unknownIDrefs; Tcl_HashTable idTables; } SchemaData; |
︙ | ︙ |
Changes to tests/schema.test.
︙ | ︙ | |||
592 593 594 595 596 597 598 599 600 601 602 603 604 605 | } } errMsg] lappend result $errMsg s delete set result } {1 {Command only allowed at lop level} 1 {Command only allowed at lop level} 1 {Method not allowed in nested schema define script} 1 {This recursive call is not allowed}} test schema-2.1 {grammar definition: ref} { tdom::schema create grammar grammar defpattern thisPattern { element a element b } grammar defpattern thatPattern { | > > > > > > > > > > > | 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 | } } errMsg] lappend result $errMsg s delete set result } {1 {Command only allowed at lop level} 1 {Command only allowed at lop level} 1 {Method not allowed in nested schema define script} 1 {This recursive call is not allowed}} test schema-1.27 {define} { tdom::schema create s set result "" s define { set ::result "from inside define" append ::result " " [expr {2+2}] } s delete set result } {from inside define 4} test schema-2.1 {grammar definition: ref} { tdom::schema create grammar grammar defpattern thisPattern { element a element b } grammar defpattern thatPattern { |
︙ | ︙ | |||
4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 | proc postValidation {g xml} { set doc [dom parse $xml] set rc [$g domvalidate $doc errMsg] $doc delete return $rc } test schema-20.1 {domunique} { set schema { prefixns {ns1 http://tdom.org/test} defelement doc { domunique ${::schema-20.1} @ref } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 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 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 | proc postValidation {g xml} { set doc [dom parse $xml] set rc [$g domvalidate $doc errMsg] $doc delete return $rc } test schema-19.1 {unique} { tdom::schema s s define { defelement doc { element a * element b * unique a @ref } defelement a { attribute ref } defelement b { attribute ref ? } } set result [list] foreach xml { <doc/> <doc><b/></doc> <doc><a/></doc> {<doc><a ref="1"/><a ref="foo"/></doc>} } { lappend result [s validate $xml] } s delete set result } {1 1 0 1} test schema-19.2 {unique} { set schema { prefixns {ns1 http://tdom.org/test} defelement doc { unique ${::schema-19.2} @ref } } set result [list] foreach ::schema-19.2 { a ./../a /foo a/b {a | b} a|b (a|b) {a/b/c | b/c/d | c/d/e} .//a //a a/@ref a/b/c a//b/c (.//b|a)/c ns1:a a/.//b/c {} { } " " ./item/./foo/. . } { tdom::schema s lappend result [catch {s define $schema}] s delete } set result } {0 1 1 0 0 0 1 0 0 1 1 0 1 1 0 1 1 1 1 0 0} test schema-19.2a {unique} { set schema { prefixns {ns1 http://tdom.org/test} defelement doc { unique ${::schema-19.2} {{@ref | div/@id} @lang} } } set result [list] foreach ::schema-19.2 { {e/b | a/b | e/f } } { tdom::schema s lappend result [catch {s define $schema}] s delete } set result } 0 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} test schema-20.1 {domunique} { set schema { prefixns {ns1 http://tdom.org/test} defelement doc { domunique ${::schema-20.1} @ref } |
︙ | ︙ | |||
4743 4744 4745 4746 4747 4748 4749 4750 | {<doc><item ref="1" id="a"/><item ref="1" id="b"/></doc>} } { lappend result [postValidation s $xml] } s delete set result } {1 0 1 0 1} | | < | 4880 4881 4882 4883 4884 4885 4886 4887 4888 | {<doc><item ref="1" id="a"/><item ref="1" id="b"/></doc>} } { lappend result [postValidation s $xml] } s delete set result } {1 0 1 0 1} } |