Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merged from schema. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | localkey |
Files: | files | file ages | folders |
SHA3-256: |
72ce7820c1aafc8a7c64fcddc2a5b434 |
User & Date: | rolf 2019-05-21 22:37:42.898 |
Context
2019-05-21
| ||
23:56 | Save work. check-in: ddad141351 user: rolf tags: localkey | |
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 | |
2019-05-18
| ||
00:41 | Save work. check-in: 4592100a23 user: rolf tags: localkey | |
Changes
Changes to generic/dom.c.
︙ | ︙ | |||
45 46 47 48 49 50 51 52 53 54 55 56 57 58 | /*--------------------------------------------------------------------------- | Includes | \--------------------------------------------------------------------------*/ #include <tcl.h> #include <dom.h> #include <domxpath.h> #include <tclexpat.h> /* #define DEBUG */ /*---------------------------------------------------------------------------- | Debug Macros | | > | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | /*--------------------------------------------------------------------------- | Includes | \--------------------------------------------------------------------------*/ #include <tcl.h> #include <dom.h> #include <domxpath.h> #include <schema.h> #include <tclexpat.h> /* #define DEBUG */ /*---------------------------------------------------------------------------- | Debug Macros | |
︙ | ︙ |
Changes to generic/dom.h.
︙ | ︙ | |||
38 39 40 41 42 43 44 | #include <tcl.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <expat.h> #include <domalloc.h> | < | 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | #include <tcl.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <expat.h> #include <domalloc.h> /* * tDOM provides it's own memory allocator which is optimized for * low heap usage. It uses the native Tcl allocator underneath, * though, but it is not very MT-friendly. Therefore, you might * use the (normal) Tcl allocator with USE_NORMAL_ALLOCATOR * defined during compile time. Actually, the symbols name is |
︙ | ︙ | |||
699 700 701 702 703 704 705 706 707 708 709 710 711 712 | /*-------------------------------------------------------------------------- | domAddCallback | \-------------------------------------------------------------------------*/ typedef int (*domAddCallback) (domNode * node, void * clientData); typedef void (*domFreeCallback) (domNode * node, void * clientData); /*-------------------------------------------------------------------------- | Function prototypes | \-------------------------------------------------------------------------*/ const char * domException2String (domException exception); | > > > > > > | 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 | /*-------------------------------------------------------------------------- | domAddCallback | \-------------------------------------------------------------------------*/ typedef int (*domAddCallback) (domNode * node, void * clientData); typedef void (*domFreeCallback) (domNode * node, void * clientData); /*-------------------------------------------------------------------------- | Forward declaration | \-------------------------------------------------------------------------*/ typedef struct SchemaData_ SchemaData; /*-------------------------------------------------------------------------- | Function prototypes | \-------------------------------------------------------------------------*/ const char * domException2String (domException exception); |
︙ | ︙ |
Changes to generic/domxpath.c.
︙ | ︙ | |||
260 261 262 263 264 265 266 267 268 269 270 271 272 273 | rs->nr_nodes = 0; } else if (rs->type == StringResult) { if (rs->string) FREE((char*)rs->string); } rs->type = EmptyResult; } void rsPrint ( xpathResultSet *rs ) { int i = 0,l; char tmp[80]; switch (rs->type) { case EmptyResult: fprintf(stderr, "empty result \n"); break; | > > > > > > > > > > > > > > > > > > > > > > | 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 | rs->nr_nodes = 0; } else if (rs->type == StringResult) { if (rs->string) FREE((char*)rs->string); } rs->type = EmptyResult; } void xpathRSReset ( xpathResultSet *rs, domNode *node ) { if (rs->type == StringResult) FREE(rs->string); if (node) { if (!rs->nodes) { rs->nodes = (domNode**)MALLOC( INITIAL_SIZE*sizeof(domNode*)); rs->allocated = INITIAL_SIZE; } rs->nodes[0] = node; rs->nr_nodes = 1; rs->type = xNodeSetResult; } else { rs->nr_nodes = 0; if (rs->nodes) rs->type = xNodeSetResult; else rs->type = EmptyResult; } } void rsPrint ( xpathResultSet *rs ) { int i = 0,l; char tmp[80]; switch (rs->type) { case EmptyResult: fprintf(stderr, "empty result \n"); break; |
︙ | ︙ | |||
5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 | CHECK_RC; DBG(rsPrint( result );) return 0; } /* xpathEval */ /*---------------------------------------------------------------------------- | xpathMatches | \---------------------------------------------------------------------------*/ int xpathMatches ( ast step, domNode * exprContext, | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 | CHECK_RC; DBG(rsPrint( result );) return 0; } /* xpathEval */ int xpathEvalAst ( ast t, xpathResultSet *nodeList, domNode *node, xpathResultSet *rs, char **errMsg ) { int i, rc, first = 1, docOrder = 1; xpathResultSet savedContext; savedContext = *nodeList; while (t) { DBG (fprintf (stderr, "xpathEvalAst: eval step '%s'\n", astType2str[t->type]);) if (t->type == Pred) { *errMsg = "Pred step not expected now!"; return XPATH_EVAL_ERR; } if (first) { rc = xpathEvalStepAndPredicates (t, nodeList, node, node, 0, &docOrder, NULL, rs, errMsg); CHECK_RC; first = 0; } else { DBG( fprintf(stderr, "doing location step nodeList->nr_nodes=%d \n", nodeList->nr_nodes); ) if (rs->type != xNodeSetResult) { *nodeList = savedContext; return 0; } *nodeList = *rs; xpathRSReset (rs, NULL); for (i=0; i < nodeList->nr_nodes; i++) { rc = xpathEvalStepAndPredicates (t, nodeList, nodeList->nodes[i], node, i, &docOrder, NULL, rs, errMsg); if (rc) { *nodeList = savedContext; return rc; } } } DBG( fprintf(stderr, "result after location step: \n"); ) DBG( rsPrint( result); ) t = t->next; /* skip the already processed Predicate parts */ while (t && t->type == Pred) t = t->next; docOrder = 1; } *nodeList = savedContext; return 0; } /*---------------------------------------------------------------------------- | xpathMatches | \---------------------------------------------------------------------------*/ int xpathMatches ( ast step, domNode * exprContext, |
︙ | ︙ |
Changes to generic/domxpath.h.
︙ | ︙ | |||
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | ast *t, char **errMsg); void xpathFreeAst (ast t); double xpathGetPrio (ast t); int xpathEval (domNode *node, domNode *exprContext, char *xpath, char **prefixMappings, xpathCBs *cbs, xpathParseVarCB *parseVarCB, Tcl_HashTable *catch, char **errMsg, xpathResultSet *rs); int xpathMatches (ast steps, domNode * exprContext, domNode *nodeToMatch, xpathCBs *cbs, char **errMsg ); int xpathEvalSteps (ast steps, xpathResultSet *nodeList, domNode *currentNode, domNode *exprContext, int currentPos, int *docOrder, xpathCBs *cbs, xpathResultSet *result, char **errMsg); #define xpathRSInit(x) (x)->type = EmptyResult; \ (x)->intvalue = 0; \ (x)->nr_nodes = 0; | > > | > | 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | ast *t, char **errMsg); void xpathFreeAst (ast t); double xpathGetPrio (ast t); int xpathEval (domNode *node, domNode *exprContext, char *xpath, char **prefixMappings, xpathCBs *cbs, xpathParseVarCB *parseVarCB, Tcl_HashTable *catch, char **errMsg, xpathResultSet *rs); int xpathEvalAst (ast t, xpathResultSet *nodeList, domNode *node, xpathResultSet *rs, char **errMsg); int xpathMatches (ast steps, domNode * exprContext, domNode *nodeToMatch, xpathCBs *cbs, char **errMsg ); int xpathEvalSteps (ast steps, xpathResultSet *nodeList, domNode *currentNode, domNode *exprContext, int currentPos, int *docOrder, xpathCBs *cbs, xpathResultSet *result, char **errMsg); #define xpathRSInit(x) (x)->type = EmptyResult; \ (x)->intvalue = 0; \ (x)->nr_nodes = 0; void xpathRSFree (xpathResultSet *rs); void xpathRSReset (xpathResultSet *rs, domNode *ode); int xpathFuncBoolean (xpathResultSet *rs); double xpathFuncNumber (xpathResultSet *rs, int *NaN); char * xpathFuncString (xpathResultSet *rs); char * xpathFuncStringForNode (domNode *node); int xpathRound (double r); |
︙ | ︙ |
Changes to generic/schema.c.
︙ | ︙ | |||
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | Tcl_Interp *interp; XML_Parser parser; Tcl_DString *cdata; int onlyWhiteSpace; char *uri; int maxUriLen; } ValidateMethodData; /*---------------------------------------------------------------------------- | Macros | \---------------------------------------------------------------------------*/ #define TMALLOC(t) (t*)MALLOC(sizeof(t)) #define SetResult(str) Tcl_ResetResult(interp); \ Tcl_SetStringObj(Tcl_GetObjResult(interp), (str), -1) #define SetResult3(str1,str2,str3) Tcl_ResetResult(interp); \ Tcl_AppendResult(interp, (str1), (str2), (str3), NULL) #define SetIntResult(i) Tcl_ResetResult(interp); \ Tcl_SetIntObj(Tcl_GetObjResult(interp), (i)) #define SetBooleanResult(i) Tcl_ResetResult(interp); \ Tcl_SetBooleanObj(Tcl_GetObjResult(interp), (i)) | > > > > > > > | | 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 | Tcl_Interp *interp; XML_Parser parser; Tcl_DString *cdata; int onlyWhiteSpace; char *uri; int maxUriLen; } ValidateMethodData; /*---------------------------------------------------------------------------- | domKeyConstraint related flage | \---------------------------------------------------------------------------*/ #define DKC_FLAG_IGNORE_EMPTY_FIELD_SET 1 /*---------------------------------------------------------------------------- | Macros | \---------------------------------------------------------------------------*/ #define TMALLOC(t) (t*)MALLOC(sizeof(t)) #define SetResult(str) Tcl_ResetResult(interp); \ Tcl_SetStringObj(Tcl_GetObjResult(interp), (str), -1) #define SetResult3(str1,str2,str3) Tcl_ResetResult(interp); \ Tcl_AppendResult(interp, (str1), (str2), (str3), NULL) #define SetIntResult(i) Tcl_ResetResult(interp); \ Tcl_SetIntObj(Tcl_GetObjResult(interp), (i)) #define SetBooleanResult(i) Tcl_ResetResult(interp); \ Tcl_SetBooleanObj(Tcl_GetObjResult(interp), (i)) #define SPACE(c) ((c) == ' ' || (c) == '\n' || (c) == '\t' || (c) == '\r') #define checkNrArgs(l,h,err) if (objc < l || objc > h) { \ SetResult (err); \ return TCL_ERROR; \ } #if defined(DEBUG) || defined(DDEBUG) |
︙ | ︙ | |||
418 419 420 421 422 423 424 425 426 427 428 429 430 431 | } FREE (kc->fields); FREE (kc); kc = knext; } } static void freeSchemaCP ( SchemaCP *pattern ) { int i; SchemaConstraint *sc; | > > > > > > > > > > > > > > > > > > > > > | 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 | } FREE (kc->fields); FREE (kc); kc = knext; } } static void freedomKeyConstraints ( domKeyConstraint *kc ) { domKeyConstraint *knext; int i; while (kc) { knext = kc->next; if (kc->name) FREE (kc->name); xpathFreeAst (kc->selector); for (i = 0; i < kc->nrFields; i++) { xpathFreeAst (kc->fields[i]); } FREE (kc->fields); FREE (kc); kc = knext; } } static void freeSchemaCP ( SchemaCP *pattern ) { int i; SchemaConstraint *sc; |
︙ | ︙ | |||
454 455 456 457 458 459 460 461 462 463 464 465 466 467 | if (pattern->attrs) { for (i = 0; i < pattern->numAttr; i++) { FREE (pattern->attrs[i]); } FREE (pattern->attrs); } freeKeyConstraints (pattern->localkeys); break; } FREE (pattern); } static SchemaData* initSchemaData ( | > | 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 | 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* initSchemaData ( |
︙ | ︙ | |||
2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 | } XML_ParserFree (parser); Tcl_DStringFree (&cdata); FREE (vdata.uri); while (sdata->stack) popStack (sdata); return result; } static int validateDOM ( Tcl_Interp *interp, SchemaData *sdata, domNode *node ) | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 | } XML_ParserFree (parser); Tcl_DStringFree (&cdata); FREE (vdata.uri); while (sdata->stack) popStack (sdata); return result; } static void schemaxpathRSFree ( xpathResultSet *rs ) { if (rs->type == StringResult) FREE (rs->string); FREE (rs->nodes); } static int checkdomKeyConstraints ( Tcl_Interp *interp, SchemaData *sdata, domNode *node ) { xpathResultSet nodeList, rs, frs; domKeyConstraint *kc; domNode *n; domAttrNode *attr; int rc, i, j, hnew, len, skip, first; char *errMsg = NULL, *keystr; Tcl_HashTable htable; Tcl_DString dStr; kc = sdata->stack->pattern->domKeys; memset (&nodeList, 0, sizeof (xpathResultSet)); nodeList.type = EmptyResult; memset (&rs, 0, sizeof (xpathResultSet)); rs.type = EmptyResult; memset (&frs, 0, sizeof (xpathResultSet)); frs.type = EmptyResult; Tcl_DStringInit (&dStr); while (kc) { xpathRSReset (&rs, NULL); xpathRSReset (&nodeList, node); Tcl_InitHashTable (&htable, TCL_STRING_KEYS); rc = xpathEvalAst (kc->selector, &nodeList, node, &rs, &errMsg); if (rc) { if (recover (interp, sdata, S("INVALID_DOM_KEYCONSTRAINT"))) { goto nextConstraint; } goto errorCleanup; } if (rs.type == EmptyResult) goto nextConstraint; if (rs.type != xNodeSetResult) { if (recover (interp, sdata, S("INVALID_DOM_KEYCONSTRAINT"))) { goto nextConstraint; } SetResult ("INVALID_DOM_KEYCONSTRAINT"); goto errorCleanup; } for (i = 0; i < rs.nr_nodes; i++) { n = rs.nodes[i]; if (n->nodeType != ELEMENT_NODE) { if (recover (interp, sdata, S("INVALID_DOM_KEYCONSTRAINT"))) { break; } SetResult ("INVALID_DOM_KEYCONSTRAINT"); goto errorCleanup; } xpathRSReset (&nodeList, n); if (kc->nrFields == 1) { xpathRSReset (&frs, NULL); rc = xpathEvalAst (kc->fields[0], &nodeList, n, &frs, &errMsg); if (rc) { if (recover (interp, sdata, S("INVALID_DOM_KEYCONSTRAINT"))) { break; } SetResult ("INVALID_DOM_KEYCONSTRAINT"); goto errorCleanup; } if (frs.type != xNodeSetResult && frs.type != EmptyResult) { if (recover (interp, sdata, S("INVALID_DOM_KEYCONSTRAINT"))) { break; } SetResult ("INVALID_DOM_KEYCONSTRAINT"); goto errorCleanup; } if (frs.type == EmptyResult || frs.nr_nodes == 0) { if (kc->flags & DKC_FLAG_IGNORE_EMPTY_FIELD_SET) { continue; } Tcl_CreateHashEntry (&htable, "", &hnew); if (!hnew) { if (recover (interp, sdata, S("DOM_KEYCONSTRAINT"))) { break; } SetResult ("DOM_KEYCONSTRAINT"); goto errorCleanup; } continue; } if (frs.nr_nodes != 1) { if (recover (interp, sdata, S("DOM_KEYCONSTRAINT"))) { break; } SetResult ("DOM_KEYCONSTRAINT"); goto errorCleanup; } if (frs.nodes[0]->nodeType != ELEMENT_NODE && frs.nodes[0]->nodeType != ATTRIBUTE_NODE) { if (recover (interp, sdata, S("INVALID_DOM_KEYCONSTRAINT"))) { break; } SetResult ("INVALID_DOM_KEYCONSTRAINT"); goto errorCleanup; } if (frs.nodes[0]->nodeType == ATTRIBUTE_NODE) { attr = (domAttrNode *) frs.nodes[0]; Tcl_CreateHashEntry (&htable, attr->nodeValue, &hnew); if (!hnew) { if (recover (interp, sdata, S("DOM_KEYCONSTRAINT"))) { break; } SetResult ("DOM_KEYCONSTRAINT"); goto errorCleanup; } } else { keystr = xpathGetStringValue (frs.nodes[0], &len); Tcl_CreateHashEntry (&htable, attr->nodeValue, &hnew); FREE(keystr); if (!hnew) { if (recover (interp, sdata, S("DOM_KEYCONSTRAINT"))) { break; } SetResult ("DOM_KEYCONSTRAINT"); goto errorCleanup; } } } else { Tcl_DStringSetLength (&dStr, 0); skip = 0; first = 1; for (j = 0; j < kc->nrFields; j++) { xpathRSReset (&frs, NULL); rc = xpathEvalAst (kc->fields[j], &nodeList, n, &frs, &errMsg); if (rc) { if (recover (interp, sdata, S("INVALID_DOM_KEYCONSTRAINT"))) { skip = 1; break; } SetResult ("INVALID_DOM_KEYCONSTRAINT"); goto errorCleanup; } if (frs.type != xNodeSetResult && frs.type != EmptyResult) { if (recover (interp, sdata, S("INVALID_DOM_KEYCONSTRAINT"))) { skip = 1; break; } SetResult ("INVALID_DOM_KEYCONSTRAINT"); goto errorCleanup; } if (frs.type == EmptyResult || frs.nr_nodes == 0) { if (kc->flags & DKC_FLAG_IGNORE_EMPTY_FIELD_SET) { continue; } if (first) first = 0; else Tcl_DStringAppend (&dStr, ":", 1); continue; } if (frs.nr_nodes != 1) { if (recover (interp, sdata, S("DOM_KEYCONSTRAINT"))) { skip = 1; break; } SetResult ("DOM_KEYCONSTRAINT"); goto errorCleanup; } if (frs.nodes[0]->nodeType != ELEMENT_NODE && frs.nodes[0]->nodeType != ATTRIBUTE_NODE) { if (recover (interp, sdata, S("INVALID_DOM_KEYCONSTRAINT"))) { skip = 1; break; } SetResult ("INVALID_DOM_KEYCONSTRAINT"); goto errorCleanup; } if (first) first = 0; else Tcl_DStringAppend (&dStr, ":", 1); if (frs.nodes[0]->nodeType == ATTRIBUTE_NODE) { attr = (domAttrNode *) frs.nodes[0]; Tcl_DStringAppend (&dStr, attr->nodeValue, attr->valueLength); } else { keystr = xpathGetStringValue (frs.nodes[0], &len); Tcl_DStringAppend (&dStr, keystr, len); } } if (skip) break; Tcl_CreateHashEntry (&htable, Tcl_DStringValue (&dStr), &hnew); if (!hnew) { if (recover (interp, sdata, S("DOM_KEYCONSTRAINT"))) { break; } SetResult ("DOM_KEYCONSTRAINT"); goto errorCleanup; } } } nextConstraint: Tcl_DeleteHashTable (&htable); kc = kc->next; } schemaxpathRSFree (&frs); schemaxpathRSFree (&rs); schemaxpathRSFree (&nodeList); return TCL_OK; errorCleanup: Tcl_DeleteHashTable (&htable); schemaxpathRSFree (&frs); schemaxpathRSFree (&rs); schemaxpathRSFree (&nodeList); return TCL_ERROR; } static int validateDOM ( Tcl_Interp *interp, SchemaData *sdata, domNode *node ) |
︙ | ︙ | |||
2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 | /* probeDomAttributes fills interp result with a msg which * required attributes are missing. */ probeDomAttributes (interp, sdata, NULL); return TCL_ERROR; } } node = node->firstChild; while (node) { switch (node->nodeType) { case ELEMENT_NODE: if (Tcl_DStringLength (sdata->cdata)) { if (probeText (interp, sdata, Tcl_DStringValue (sdata->cdata)) != TCL_OK) | > > > > > | 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 | /* probeDomAttributes fills interp result with a msg which * required attributes are missing. */ probeDomAttributes (interp, sdata, NULL); return TCL_ERROR; } } if (sdata->stack->pattern->domKeys) { if (checkdomKeyConstraints (interp, sdata, node) != TCL_OK) return TCL_ERROR; } node = node->firstChild; while (node) { switch (node->nodeType) { case ELEMENT_NODE: if (Tcl_DStringLength (sdata->cdata)) { if (probeText (interp, sdata, Tcl_DStringValue (sdata->cdata)) != TCL_OK) |
︙ | ︙ | |||
3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 | while (kc1->next) kc1 = kc1->next; kc1->next = kc; } else { sdata->cp->localkeys = kc; } return TCL_OK; } static int integerImpl ( Tcl_Interp *interp, void *constraintData, char *text ) | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 | 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[] ) { SchemaData *sdata = GETASI; ast t; char *errMsg = NULL; domKeyConstraint *kc; int i, nrFields, flags = 0, nrFlags; Tcl_Obj *elm; CHECK_SI CHECK_TOPLEVEL checkNrArgs (3, 5, "Expected: <selector> <fieldlist> ?<name>? ?flags?"); if (sdata->cp->type != SCHEMA_CTYPE_NAME) { SetResult ("The domunique schema definition command is only " "allowed as direct child of an element."); } if (Tcl_ListObjLength (interp, objv[2], &nrFields) != TCL_OK) { SetResult ("The <fieldlist> argument must be a valid tcl list"); return TCL_ERROR; } if (nrFields == 0) { SetResult ("Non empty fieldlist arugment expected."); xpathFreeAst (t); return TCL_ERROR; } if (objc == 5) { if (Tcl_ListObjLength (interp, objv[4], &nrFlags) != TCL_OK) { SetResult ("The <flags> argument must be a valid tcl list"); return TCL_ERROR; } for (i = 0; i < nrFlags; i++) { Tcl_ListObjIndex (interp, objv[4], i, &elm); if (strcmp ("IGNORE_EMPTY_FIELD_SET", Tcl_GetString (elm)) == 0) { flags |= DKC_FLAG_IGNORE_EMPTY_FIELD_SET; continue; } SetResult3 ("Unknown flag '", Tcl_GetString (elm), "'"); return TCL_ERROR; } } 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; } kc = TMALLOC (domKeyConstraint); memset (kc, 0, sizeof (domKeyConstraint)); kc->fields = MALLOC (sizeof (ast) * nrFields); memset (kc->fields, 0, sizeof (ast) * nrFields); kc->nrFields = nrFields; kc->selector = t; kc->flags = flags; 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); freedomKeyConstraints (kc); return TCL_ERROR; } kc->fields[i] = t; } if (objc == 4) { kc->name = tdomstrdup (Tcl_GetString (objv[3])); } kc->next = sdata->cp->domKeys; sdata->cp->domKeys = kc; return TCL_OK; } static int integerImpl ( Tcl_Interp *interp, void *constraintData, char *text ) |
︙ | ︙ | |||
5108 5109 5110 5111 5112 5113 5114 | /* 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); | > > > | | 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 | /* 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); Tcl_CreateObjCommand (interp, "tdom::schema::text::tcl", tclTCObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp, "tdom::schema::text::fixed", fixedTCObjCmd, NULL, NULL); |
︙ | ︙ |
Changes to generic/schema.h.
︙ | ︙ | |||
20 21 22 23 24 25 26 27 28 29 30 31 32 33 | | 2018-2019 | \---------------------------------------------------------------------------*/ #ifndef __SCHEMA_H__ #define __SCHEMA_H__ typedef enum { SCHEMA_CTYPE_ANY, SCHEMA_CTYPE_NAME, SCHEMA_CTYPE_CHOICE, SCHEMA_CTYPE_INTERLEAVE, SCHEMA_CTYPE_PATTERN, SCHEMA_CTYPE_TEXT, | > > > | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | | 2018-2019 | \---------------------------------------------------------------------------*/ #ifndef __SCHEMA_H__ #define __SCHEMA_H__ #include <tcldom.h> #include <domxpath.h> typedef enum { SCHEMA_CTYPE_ANY, SCHEMA_CTYPE_NAME, SCHEMA_CTYPE_CHOICE, SCHEMA_CTYPE_INTERLEAVE, SCHEMA_CTYPE_PATTERN, SCHEMA_CTYPE_TEXT, |
︙ | ︙ | |||
67 68 69 70 71 72 73 74 75 76 77 78 79 80 | /* The SchemaFlags flags */ #define FORWARD_PATTERN_DEF 1 #define PLACEHOLDER_PATTERN_DEF 2 #define AMBIGUOUS_PATTERN 4 #define LOCAL_DEFINED_ELEMENT 8 #define CONSTRAINT_TEXT_CHILD 16 #define MIXED_CONTENT 32 typedef enum { SCHEMA_KEY_UNIQUE, SCHEMA_KEY_KEY, SCHEMA_KEY_KEYREF } KeyType; | > > > > > > > > > | 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | /* The SchemaFlags flags */ #define FORWARD_PATTERN_DEF 1 #define PLACEHOLDER_PATTERN_DEF 2 #define AMBIGUOUS_PATTERN 4 #define LOCAL_DEFINED_ELEMENT 8 #define CONSTRAINT_TEXT_CHILD 16 #define MIXED_CONTENT 32 typedef struct domKeyConstraint { char *name; ast selector; ast *fields; int nrFields; int flags; struct domKeyConstraint *next; } domKeyConstraint; typedef enum { SCHEMA_KEY_UNIQUE, SCHEMA_KEY_KEY, SCHEMA_KEY_KEYREF } KeyType; |
︙ | ︙ | |||
129 130 131 132 133 134 135 | struct SchemaCP **content; SchemaQuant *quants; unsigned int nc; SchemaAttr **attrs; unsigned int numAttr; unsigned int numReqAttr; KeyConstraint *localkeys; | | | 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | 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; |
︙ | ︙ | |||
156 157 158 159 160 161 162 | typedef struct { Tcl_HashTable ids; int unknownIDrefs; } SchemaDocKey; | | | 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | typedef struct { Tcl_HashTable ids; int unknownIDrefs; } SchemaDocKey; typedef struct SchemaData_ { Tcl_Obj *self; char *start; char *startNamespace; Tcl_HashTable element; Tcl_HashTable namespace; Tcl_HashEntry *emptyNamespace; |
︙ | ︙ |
Changes to tests/schema.test.
︙ | ︙ | |||
4742 4743 4744 4745 4746 4747 4748 4749 4750 | {<doc><item lang="de"/><item lang="en"/><item lang="fr"/></doc>} } { lappend result [s validate $xml] } s delete set result } {1} } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 | {<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 } } set result [list] foreach ::schema-20.1 { 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[1]/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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1} test schema-20.2 {domunique} { tdom::schema s s define { defelement doc { domunique item @ref element item * { attribute ref ? } } } set result [list] foreach xml { {<doc><item ref="1"/><item ref="foo"/></doc>} {<doc><item ref="1"/><item ref="1"/></doc>} {<doc><item/><item ref="1"/></doc>} {<doc><item/><item/></doc>} } { lappend result [postValidation s $xml] } s delete set result } {1 0 1 0} test schema-20.2a {domunique} { tdom::schema s s define { defelement doc { domunique item @ref itemrefkey IGNORE_EMPTY_FIELD_SET element item * { attribute ref ? } } } set result [list] foreach xml { {<doc><item ref="1"/><item ref="foo"/></doc>} {<doc><item ref="1"/><item ref="1"/></doc>} {<doc><item/><item ref="1"/></doc>} {<doc><item/><item/></doc>} } { lappend result [postValidation s $xml] } s delete set result } {1 0 1 1} test schema-20.3 {domunique} { tdom::schema s s define { defelement doc { element items * { element item * { attribute ref ? } domunique item @ref } } } set result [list] foreach xml { {<doc><items><item ref="1"/><item ref="foo"/></items></doc>} {<doc><items><item ref="1"/><item ref="1"/></items></doc>} {<doc><items><item ref="1"/><item ref="foo"/></items><items><item ref="1"/><item ref="foo"/></items></doc>} {<doc><items><item ref="1"/><item ref="foo"/></items><items><item ref="1"/><item ref="bar"/></items></doc>} {<doc><items><item ref="1"/><item ref="foo"/></items><items><item ref="2"/><item ref="bar"/></items></doc>} {<doc><items><item ref="1"/><item ref="foo"/></items><items><item ref="bar"/><item ref="bar"/></items></doc>} } { lappend result [postValidation s $xml] } s delete set result } {1 0 1 1 1 0} test schema-20.4 {domunique} { tdom::schema s s define { defelement doc { domunique item {@ref @id} element item * { attribute ref ? attribute id ? } } } set result [list] foreach xml { {<doc><item ref="1"/><item ref="foo"/></doc>} {<doc><item ref="1"/><item ref="1"/></doc>} {<doc><item ref="1" id="a"/><item ref="foo" id="a"/></doc>} {<doc><item ref="1" id="a"/><item ref="1" id="a"/></doc>} {<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} } |