Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Integrated so far done work: bug fixes in recoving, more work on sanitizing recovering, code gardening. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | schema |
Files: | files | file ages | folders |
SHA3-256: |
33ac16a9c250c5ccb1fa22475ea2b140 |
User & Date: | rolf 2020-03-19 02:21:01.213 |
Context
2020-03-27
| ||
00:54 | Merged so far done work: recovering script may now decide about recover strategy by return value in case of MISSING_ELEMENT with element start event. Beside the default "ignore the element and the rest of the current parent element content and continue with the parents sibling" now there is "ignore", advising the validation engine to pretend the missing mandatory element had matched and we are looking for the element start event from there, and "vanish", advising the validation engine to skip the element as it would haven't been in the input XML. In case of UNEXPECTED_ELEMENT in element start event the result "vanish" advices the validation engine to skip the element (which allows to see further unexpected elements in the source). check-in: f90aa277b4 user: rolf tags: schema | |
2020-03-20
| ||
02:31 | Working on more control over recovering for certain events. check-in: a07b509a44 user: rolf tags: wip | |
2020-03-19
| ||
02:21 | Integrated so far done work: bug fixes in recoving, more work on sanitizing recovering, code gardening. check-in: 33ac16a9c2 user: rolf tags: schema | |
02:15 | Made the default recover behaviour at element end the same as for element start: skip and continue at the sibling of the current subtree. Closed-Leaf check-in: 0037ce9df3 user: rolf tags: wip | |
2020-03-17
| ||
23:55 | Micro optimization. check-in: fd743f35c1 user: rolf tags: schema | |
Changes
Changes to generic/schema.c.
︙ | ︙ | |||
163 164 165 166 167 168 169 | "INVALID_KEYREF", "UNKNOWN_ROOT_ELEMENT", "UNKOWN_GLOBAL_ID", "UNKOWN_ID", "INVALID_ATTRIBUTE_VALUE", "INVALID_VALUE" }; | | > > > > > > > > | 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | "INVALID_KEYREF", "UNKNOWN_ROOT_ELEMENT", "UNKOWN_GLOBAL_ID", "UNKOWN_ID", "INVALID_ATTRIBUTE_VALUE", "INVALID_VALUE" }; /*---------------------------------------------------------------------------- | Recover related flage | \---------------------------------------------------------------------------*/ #define RECOVER_FLAG_REWIND 1 #define RECOVER_FLAG_DONT_REPORT 2 /*---------------------------------------------------------------------------- | domKeyConstraint related flage | \---------------------------------------------------------------------------*/ #define DKC_FLAG_IGNORE_EMPTY_FIELD_SET 1 #define DKC_FLAG_BOOLEAN 2 |
︙ | ︙ | |||
288 289 290 291 292 293 294 | } #define CHECK_EVAL \ if (sdata->currentEvals) { \ SetResult ("This method is not allowed in nested evaluation"); \ return TCL_ERROR; \ } | | > > > > > > | 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 | } #define CHECK_EVAL \ if (sdata->currentEvals) { \ SetResult ("This method is not allowed in nested evaluation"); \ return TCL_ERROR; \ } #define CHECK_REWIND \ if (sdata->recoverFlags & RECOVER_FLAG_REWIND) { \ rewindStack (sdata); \ sdata->recoverFlags &= ~RECOVER_FLAG_REWIND; \ } \ #define REMEMBER_PATTERN(pattern) \ if (sdata->numPatternList == sdata->patternListSize) { \ sdata->patternList = (SchemaCP **) REALLOC ( \ sdata->patternList, \ sizeof (SchemaCP*) * sdata->patternListSize * 2); \ sdata->patternListSize *= 2; \ } \ |
︙ | ︙ | |||
347 348 349 350 351 352 353 | hm = se->hasMatched; \ if (hm && maxOne (cp->quants[ac])) { \ ac += + 1; \ hm = 0; \ } \ | | > | | > | | 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 | hm = se->hasMatched; \ if (hm && maxOne (cp->quants[ac])) { \ ac += + 1; \ hm = 0; \ } \ #define updateStack(sdata,cp,ac) \ if (!(sdata->recoverFlags & RECOVER_FLAG_REWIND)) { \ se->activeChild = ac; \ se->hasMatched = 1; \ } \ static SchemaCP* initSchemaCP ( Schema_CP_Type type, void *namespace, char *name ) { |
︙ | ︙ | |||
1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 | } popStack (sdata); /* cp is still the pattern from stack top before the popStack */ if (cp->type != SCHEMA_CTYPE_NAME) { finalizeElement (sdata, sdata->stack->activeChild + 1); } } static int recover ( Tcl_Interp *interp, SchemaData *sdata, ValidationErrorType errorType, const char *name, const char *ns, char *text, int ac ) { Tcl_Obj *cmdPtr; int rc; SchemaValidationStack *se; if (!sdata->reportCmd || sdata->evalError) return 0; /* If non SCHEMA_CTYPE_NAME and the pattern hasn't already matched * that's a pattern pushed on stack to look for (probe) if it * matches (or allows empty match). Even if the pattern fail it * may be optional; recovering is done at the caller level in case * the pattern isn't optional. */ if (sdata->stack && sdata->stack->pattern->type != SCHEMA_CTYPE_NAME | > > > > > > > > > > > > > > > > | 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 | } popStack (sdata); /* cp is still the pattern from stack top before the popStack */ if (cp->type != SCHEMA_CTYPE_NAME) { finalizeElement (sdata, sdata->stack->activeChild + 1); } } static void rewindStack ( SchemaData *sdata ) { SchemaValidationStack *se; while (sdata->lastMatchse) { se = sdata->lastMatchse; sdata->lastMatchse = se->down; se->down = sdata->stack; sdata->stack = se; } } static int recover ( Tcl_Interp *interp, SchemaData *sdata, ValidationErrorType errorType, const char *name, const char *ns, char *text, int ac ) { Tcl_Obj *cmdPtr; int rc; SchemaValidationStack *se; if (!sdata->reportCmd || sdata->evalError) return 0; if (sdata->recoverFlags & RECOVER_FLAG_DONT_REPORT) return 1; /* If non SCHEMA_CTYPE_NAME and the pattern hasn't already matched * that's a pattern pushed on stack to look for (probe) if it * matches (or allows empty match). Even if the pattern fail it * may be optional; recovering is done at the caller level in case * the pattern isn't optional. */ if (sdata->stack && sdata->stack->pattern->type != SCHEMA_CTYPE_NAME |
︙ | ︙ | |||
1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 | } switch (errorType) { case MISSING_ELEMENT_MATCH_START: case UNEXPECTED_ELEMENT: finalizeElement (sdata, ac+1); sdata->skipDeep = 2; break; case DOM_KEYCONSTRAINT: case DOM_XPATH_BOOLEAN: case MISSING_ATTRIBUTE: | > > > > > > > < < < | 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 | } switch (errorType) { case MISSING_ELEMENT_MATCH_START: case UNEXPECTED_ELEMENT: finalizeElement (sdata, ac+1); sdata->skipDeep = 2; break; case UNEXPECTED_TEXT: sdata->recoverFlags |= RECOVER_FLAG_REWIND; break; case MISSING_ELEMENT_MATCH_END: case MISSING_TEXT_MATCH_END: sdata->recoverFlags |= RECOVER_FLAG_DONT_REPORT; break; case DOM_KEYCONSTRAINT: case DOM_XPATH_BOOLEAN: case MISSING_ATTRIBUTE: case MISSING_TEXT_MATCH_START: case UNEXPECTED_ROOT_ELEMENT: case UNKNOWN_ATTRIBUTE: case INVALID_KEYREF_MATCH_START: case INVALID_KEYREF_MATCH_END: case INVALID_KEYREF_MATCH_TEXT: case UNKNOWN_ROOT_ELEMENT: case UNKOWN_GLOBAL_ID: |
︙ | ︙ | |||
1231 1232 1233 1234 1235 1236 1237 | break; case SCHEMA_CTYPE_ANY: if (candidate->namespace && candidate->namespace != namespace) { break; } | | | | | | | | 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 | break; case SCHEMA_CTYPE_ANY: if (candidate->namespace && candidate->namespace != namespace) { break; } updateStack (sdata, cp, ac); sdata->skipDeep = 1; /* See comment in probeElement: sdata->vname and * sdata->vns may be pre-filled. We reset it here.*/ sdata->vname = NULL; sdata->vns = NULL; return 1; case SCHEMA_CTYPE_NAME: DBG(fprintf (stderr, "name: %s ns: %s candidate name: %s " "candidate ns: %s\n", name, namespace, candidate->name, candidate->namespace)); if (candidate->name == name && candidate->namespace == namespace) { pushToStack (sdata, candidate); updateStack (sdata, cp, ac); return 1; } break; case SCHEMA_CTYPE_CHOICE: if (candidate->typedata) { h = Tcl_FindHashEntry ((Tcl_HashTable *)candidate->typedata, name); if (h) { icp = Tcl_GetHashValue (h); if (icp->namespace == namespace) { pushToStack (sdata, icp); updateStack (sdata, cp, ac); return 1; } } /* TODO: Short-cut in case of no match (looking * for emtpy match, recovering). For now fall * throu to simple, serial approach. */ } for (i = 0; i < candidate->nc; i++) { icp = candidate->content[i]; switch (icp->type) { case SCHEMA_CTYPE_TEXT: break; case SCHEMA_CTYPE_ANY: if (icp->namespace && icp->namespace != namespace) { break; } updateStack (sdata, cp, ac); sdata->skipDeep = 1; /* See comment in probeElement: sdata->vname * and sdata->vns may be pre-filled. We reset it * here.*/ sdata->vname = NULL; sdata->vns = NULL; return 1; case SCHEMA_CTYPE_NAME: if (icp->name == name && icp->namespace == namespace) { pushToStack (sdata, icp); updateStack (sdata, cp, ac); return 1; } break; case SCHEMA_CTYPE_CHOICE: Tcl_Panic ("MIXED or CHOICE child of MIXED or CHOICE"); case SCHEMA_CTYPE_INTERLEAVE: case SCHEMA_CTYPE_PATTERN: pushToStack (sdata, icp); rc = matchElementStart (interp, sdata, name, namespace); if (rc == 1) { updateStack (sdata, cp, ac); return 1; } popStack (sdata); if (rc == -1) mayskip = 1; break; case SCHEMA_CTYPE_VIRTUAL: |
︙ | ︙ | |||
1335 1336 1337 1338 1339 1340 1341 | else return 0; case SCHEMA_CTYPE_INTERLEAVE: case SCHEMA_CTYPE_PATTERN: pushToStack (sdata, candidate); rc = matchElementStart (interp, sdata, name, namespace); if (rc == 1) { | | | 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 | else return 0; case SCHEMA_CTYPE_INTERLEAVE: case SCHEMA_CTYPE_PATTERN: pushToStack (sdata, candidate); rc = matchElementStart (interp, sdata, name, namespace); if (rc == 1) { updateStack (sdata, cp, ac); return 1; } popStack (sdata); if (rc == -1) mayskip = 1; break; case SCHEMA_CTYPE_KEYSPACE_END: |
︙ | ︙ | |||
2028 2029 2030 2031 2032 2033 2034 | static int checkElementEnd ( Tcl_Interp *interp, SchemaData *sdata ) { SchemaValidationStack *se; SchemaCP *cp, *ic; | | | 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 | static int checkElementEnd ( Tcl_Interp *interp, SchemaData *sdata ) { SchemaValidationStack *se; SchemaCP *cp, *ic; int hm, ac, i, mayskip, rc; int isName = 0; DBG(fprintf (stderr, "checkElementEnd:\n"); serializeStack(sdata);); se = sdata->stack; getContext (cp, ac, hm); |
︙ | ︙ | |||
2092 2093 2094 2095 2096 2097 2098 | } return 0; } } break; case SCHEMA_CTYPE_CHOICE: | | | | | | | | 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 | } return 0; } } break; case SCHEMA_CTYPE_CHOICE: mayskip = 0; for (i = 0; i < cp->content[ac]->nc; i++) { if (mayMiss (cp->content[ac]->quants[i])) { mayskip = 1; break; } ic = cp->content[ac]->content[i]; switch (ic->type) { case SCHEMA_CTYPE_TEXT: if (ic->nc) { if (!checkText (interp, ic, "")) { continue; } } mayskip = 1; break; case SCHEMA_CTYPE_NAME: case SCHEMA_CTYPE_ANY: continue; case SCHEMA_CTYPE_INTERLEAVE: case SCHEMA_CTYPE_PATTERN: pushToStack (sdata, ic); if (checkElementEnd (interp, sdata)) { mayskip = 1; } popStack (sdata); break; case SCHEMA_CTYPE_KEYSPACE_END: case SCHEMA_CTYPE_KEYSPACE: case SCHEMA_CTYPE_VIRTUAL: case SCHEMA_CTYPE_CHOICE: Tcl_Panic ("Invalid CTYPE in MIXED or CHOICE"); } if (mayskip) break; } if (mayskip) break; if (!recover (interp, sdata, MISSING_ELEMENT_MATCH_END, NULL, NULL, NULL, 0)) { return 0; } break; case SCHEMA_CTYPE_VIRTUAL: |
︙ | ︙ | |||
2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 | } rc = checkElementEnd (interp, sdata); while (rc == -1) { popStack (sdata); rc = checkElementEnd (interp, sdata); } if (rc) { popStack (sdata); if (sdata->stack == NULL) { /* End of the first pattern (the tree root) without error. */ /* Check for unknown ID references */ if (!checkDocKeys (interp, sdata)) { return TCL_ERROR; | > | 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 | } rc = checkElementEnd (interp, sdata); while (rc == -1) { popStack (sdata); rc = checkElementEnd (interp, sdata); } sdata->recoverFlags &= ~RECOVER_FLAG_DONT_REPORT; if (rc) { popStack (sdata); if (sdata->stack == NULL) { /* End of the first pattern (the tree root) without error. */ /* Check for unknown ID references */ if (!checkDocKeys (interp, sdata)) { return TCL_ERROR; |
︙ | ︙ | |||
2327 2328 2329 2330 2331 2332 2333 | Tcl_Interp *interp, SchemaData *sdata, char *text ) { SchemaCP *cp, *candidate, *ic; SchemaValidationStack *se; | | < | | > | | | | | | 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 | Tcl_Interp *interp, SchemaData *sdata, char *text ) { SchemaCP *cp, *candidate, *ic; SchemaValidationStack *se; int ac, hm, isName = 0, i, mayskip; DBG(fprintf (stderr, "matchText called with text '%s'\n", text)); se = sdata->stack; getContext (cp, ac, hm); while (1) { switch (cp->type) { case SCHEMA_CTYPE_NAME: isName = 1; /* Fall through */ case SCHEMA_CTYPE_PATTERN: while (ac < cp->nc) { candidate = cp->content[ac]; switch (candidate->type) { case SCHEMA_CTYPE_TEXT: if (checkText (interp, candidate, text)) { updateStack (sdata, cp, ac); return 1; } if (sdata->evalError) return 0; if (recover (interp, sdata, INVALID_VALUE, NULL, NULL, text, ac)) { updateStack (sdata, cp, ac); return 1; } SetResult ("Invalid text content"); return 0; case SCHEMA_CTYPE_CHOICE: if (candidate->flags & MIXED_CONTENT) { updateStack (sdata, cp, ac); return 1; } for (i = 0; i < candidate->nc; i++) { ic = candidate->content[i]; switch (ic->type) { case SCHEMA_CTYPE_TEXT: if (checkText (interp, ic, text)) { updateStack (sdata, cp, ac); return 1; } break; case SCHEMA_CTYPE_NAME: case SCHEMA_CTYPE_ANY: break; case SCHEMA_CTYPE_INTERLEAVE: case SCHEMA_CTYPE_PATTERN: pushToStack (sdata, ic); if (matchText (interp, sdata, text)) { updateStack (sdata, cp, ac); return 1; } popStack (sdata); break; case SCHEMA_CTYPE_VIRTUAL: Tcl_Panic ("Virtual constrain in MIXED or" |
︙ | ︙ | |||
2403 2404 2405 2406 2407 2408 2409 | " CHOICE"); } } if (mustMatch (cp->quants[ac], hm)) { if (recover (interp, sdata, UNEXPECTED_TEXT, NULL, NULL, text, 0)) { | | | | | 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 | " CHOICE"); } } if (mustMatch (cp->quants[ac], hm)) { if (recover (interp, sdata, UNEXPECTED_TEXT, NULL, NULL, text, 0)) { return 1; } SetResultV ("Unexpected text content"); return 0; } break; case SCHEMA_CTYPE_INTERLEAVE: case SCHEMA_CTYPE_PATTERN: pushToStack (sdata, candidate); if (matchText (interp, sdata, text)) { updateStack (sdata, cp, ac); return 1; } popStack (sdata); if (mustMatch (cp->quants[ac], hm)) { if (recover (interp, sdata, UNEXPECTED_TEXT, NULL, NULL, text, 0)) { return 1; } SetResultV ("Unexpected text content"); return 0; } break; case SCHEMA_CTYPE_VIRTUAL: |
︙ | ︙ | |||
2463 2464 2465 2466 2467 2468 2469 | break; case SCHEMA_CTYPE_NAME: case SCHEMA_CTYPE_ANY: if (mustMatch (cp->quants[ac], hm)) { if (recover (interp, sdata, UNEXPECTED_TEXT, NULL, NULL, text, ac)) { | | > > > > > > > > > | > > > | | > > > > > > > > > > > | 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 | break; case SCHEMA_CTYPE_NAME: case SCHEMA_CTYPE_ANY: if (mustMatch (cp->quants[ac], hm)) { if (recover (interp, sdata, UNEXPECTED_TEXT, NULL, NULL, text, ac)) { return 1; } SetResultV ("Unexpected text content"); return 0; } break; } ac++; } if (isName) { if (recover (interp, sdata, UNEXPECTED_TEXT, NULL, NULL, text, 0)) { return 1; } SetResultV ("Unexpected text content"); return 0; } popStack (sdata); se = sdata->stack; getContext (cp, ac, hm); ac++; continue; case SCHEMA_CTYPE_KEYSPACE: case SCHEMA_CTYPE_KEYSPACE_END: case SCHEMA_CTYPE_VIRTUAL: case SCHEMA_CTYPE_CHOICE: case SCHEMA_CTYPE_TEXT: case SCHEMA_CTYPE_ANY: /* Never pushed onto stack */ Tcl_Panic ("Invalid CTYPE onto the validation stack!"); break; case SCHEMA_CTYPE_INTERLEAVE: mayskip = 1; for (i = 0; i < cp->nc; i++) { if (se->interleaveState[i]) { if (maxOne (cp->quants[i])) continue; } else { if (minOne (cp->quants[i])) mayskip = 0; } ic = cp->content[i]; switch (ic->type) { case SCHEMA_CTYPE_TEXT: if (checkText (interp, ic, text)) { se->hasMatched = 1; se->interleaveState[i] = 1; return 1; } break; case SCHEMA_CTYPE_NAME: case SCHEMA_CTYPE_ANY: break; case SCHEMA_CTYPE_INTERLEAVE: case SCHEMA_CTYPE_PATTERN: pushToStack (sdata, ic); if (matchText (interp, sdata, text)) { updateStack (sdata, cp, ac); return 1; } popStack (sdata); break; case SCHEMA_CTYPE_CHOICE: Tcl_Panic ("MIXED or CHOICE child of INTERLEAVE"); case SCHEMA_CTYPE_KEYSPACE_END: case SCHEMA_CTYPE_KEYSPACE: Tcl_Panic ("Keyspace child of INTERLEAVE"); case SCHEMA_CTYPE_VIRTUAL: break; } } if (!mayskip) { if (recover (interp, sdata, UNEXPECTED_TEXT, NULL, NULL, text, ac)) { return 1; } SetResultV ("Unexpected text content"); return 0; } popStack (sdata); se = sdata->stack; getContext (cp, ac, hm); ac++; continue; } /* Not reached, but this is inside a while (1) {} loop ...*/ break; } /* Not reached, but at least makes the compiler happy. */ return 0; } int probeText ( Tcl_Interp *interp, SchemaData *sdata, |
︙ | ︙ | |||
2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 | if (sdata->validationState == VALIDATION_READY) { SetResult ("No validation started"); return TCL_ERROR; } if (sdata->stack->pattern->flags & CONSTRAINT_TEXT_CHILD) { if (matchText (interp, sdata, text)) { return TCL_OK; } } else { only_whites = 1; pc = text; while (*pc) { if ( (*pc == ' ') || (*pc == '\n') || (*pc == '\r') || (*pc == '\t') ) { pc++; continue; } only_whites = 0; break; } if (only_whites) return TCL_OK; if (matchText (interp, sdata, text)) { return TCL_OK; } } if (!sdata->evalError) { SetResult ("Text content doesn't match"); } return TCL_ERROR; | > > | 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 | if (sdata->validationState == VALIDATION_READY) { SetResult ("No validation started"); return TCL_ERROR; } if (sdata->stack->pattern->flags & CONSTRAINT_TEXT_CHILD) { if (matchText (interp, sdata, text)) { CHECK_REWIND; return TCL_OK; } } else { only_whites = 1; pc = text; while (*pc) { if ( (*pc == ' ') || (*pc == '\n') || (*pc == '\r') || (*pc == '\t') ) { pc++; continue; } only_whites = 0; break; } if (only_whites) return TCL_OK; if (matchText (interp, sdata, text)) { CHECK_REWIND; return TCL_OK; } } if (!sdata->evalError) { SetResult ("Text content doesn't match"); } return TCL_ERROR; |
︙ | ︙ | |||
3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 | Tcl_HashEntry *h; Tcl_HashSearch search; SchemaDocKey *dk; SchemaKeySpace *ks; while (sdata->stack) popStack (sdata); while (sdata->lastMatchse) popFromStack (sdata, &sdata->lastMatchse); sdata->validationState = VALIDATION_READY; sdata->skipDeep = 0; sdata->evalError = 0; sdata->vaction = 0; sdata->vname = NULL; sdata->vns = NULL; sdata->vtext = NULL; | > | 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 | Tcl_HashEntry *h; Tcl_HashSearch search; SchemaDocKey *dk; SchemaKeySpace *ks; while (sdata->stack) popStack (sdata); while (sdata->lastMatchse) popFromStack (sdata, &sdata->lastMatchse); sdata->recoverFlags = 0; sdata->validationState = VALIDATION_READY; sdata->skipDeep = 0; sdata->evalError = 0; sdata->vaction = 0; sdata->vname = NULL; sdata->vns = NULL; sdata->vtext = NULL; |
︙ | ︙ |
Changes to generic/schema.h.
︙ | ︙ | |||
161 162 163 164 165 166 167 168 169 170 171 172 173 174 | SchemaQuant *quants; int inuse; int currentEvals; int cleanupAfterUse; int evalError; Tcl_Obj *reportCmd; SchemaValidationStack *lastMatchse; Tcl_Obj **evalStub; Tcl_Obj **textStub; char *currentNamespace; int defineToplevel; int isTextConstraint; int isAttributeConstaint; SchemaCP *cp; | > | 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | SchemaQuant *quants; int inuse; int currentEvals; int cleanupAfterUse; int evalError; Tcl_Obj *reportCmd; SchemaValidationStack *lastMatchse; int recoverFlags; Tcl_Obj **evalStub; Tcl_Obj **textStub; char *currentNamespace; int defineToplevel; int isTextConstraint; int isAttributeConstaint; SchemaCP *cp; |
︙ | ︙ |
Changes to tests/schema.test.
︙ | ︙ | |||
14 15 16 17 18 19 20 | # schema-11.*: attribute, nsattribute # schema-12.*: schemaCmd domvalidate # schema-13.*: XML namespaces # schema-14.*: text # schema-15.*: Constraint cmd tcl # schema-16.*: interleave # schema-17.*: info | | | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | # schema-11.*: attribute, nsattribute # schema-12.*: schemaCmd domvalidate # schema-13.*: XML namespaces # schema-14.*: text # schema-15.*: Constraint cmd tcl # schema-16.*: interleave # schema-17.*: info # schema-18.*: reportcmd, validation error recover # schema-19.*: keyspace # schema-20.*: domunique # schema-21.*: internal: buffers # schema-22.*: defelementtype, elementtype # schema-23.*: validatefile # schema-24.*: validatechannel # schema-25.*: domxpathboolean |
︙ | ︙ | |||
7284 7285 7286 7287 7288 7289 7290 | } s reportcmd schema-18 set result "" set rc [s validate {<doc><e/></doc>}] lappend result $rc s delete set result | | | 7284 7285 7286 7287 7288 7289 7290 7291 7292 7293 7294 7295 7296 7297 7298 | } s reportcmd schema-18 set result "" set rc [s validate {<doc><e/></doc>}] lappend result $rc s delete set result } {s MISSING_TEXT 1} test schema-18.1a {reportcmd} { tdom::schema s s define { defelement doc { element e text {minLength 1} |
︙ | ︙ | |||
7675 7676 7677 7678 7679 7680 7681 | {<doc><e attr2="123" foo=""/></doc>} } { lappend result [s validate $xml] } s delete set result } {1 INVALID_ATTRIBUTE_VALUE {{<elementend> {}}} MATCH_ATTRIBUTE_TEXT attr2 {} a MISSING_ATTRIBUTE {{<elementend> {}}} MATCH_ELEMENT_START attr1 {} {} 1 UNKNOWN_ATTRIBUTE {{<elementend> {}}} MATCH_ELEMENT_START foo {} {} MISSING_ATTRIBUTE {{<elementend> {}}} MATCH_ELEMENT_START attr1 {} {} 1} | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 7675 7676 7677 7678 7679 7680 7681 7682 7683 7684 7685 7686 7687 7688 7689 7690 7691 7692 7693 7694 7695 7696 7697 7698 7699 7700 7701 7702 7703 7704 7705 7706 7707 7708 7709 7710 7711 7712 7713 7714 7715 7716 7717 7718 7719 7720 7721 7722 7723 7724 7725 7726 7727 7728 7729 7730 7731 7732 7733 7734 7735 7736 7737 7738 7739 7740 7741 7742 7743 7744 7745 7746 7747 7748 7749 7750 7751 7752 7753 7754 7755 7756 7757 7758 7759 7760 7761 7762 7763 7764 7765 7766 7767 7768 7769 7770 7771 7772 7773 7774 7775 7776 7777 7778 7779 7780 7781 7782 7783 7784 7785 7786 7787 7788 7789 7790 7791 7792 7793 7794 7795 7796 7797 7798 7799 7800 7801 7802 7803 7804 7805 7806 7807 7808 7809 7810 7811 7812 7813 7814 7815 7816 7817 7818 7819 7820 7821 7822 7823 7824 7825 7826 7827 7828 7829 7830 7831 7832 7833 7834 7835 7836 7837 7838 7839 7840 7841 7842 7843 7844 7845 7846 7847 7848 7849 7850 7851 7852 7853 7854 7855 | {<doc><e attr2="123" foo=""/></doc>} } { lappend result [s validate $xml] } s delete set result } {1 INVALID_ATTRIBUTE_VALUE {{<elementend> {}}} MATCH_ATTRIBUTE_TEXT attr2 {} a MISSING_ATTRIBUTE {{<elementend> {}}} MATCH_ELEMENT_START attr1 {} {} 1 UNKNOWN_ATTRIBUTE {{<elementend> {}}} MATCH_ELEMENT_START foo {} {} MISSING_ATTRIBUTE {{<elementend> {}}} MATCH_ELEMENT_START attr1 {} {} 1} proc appendtoresult {scmd errortype} { lappend ::result $errortype } test schema-18.16 {unexpected text} { set defs { { defelement doc { ref r1 } defpattern r1 { element e ? {} } } { defelement doc { element e ? {} } } } set result [list] foreach def $defs { tdom::schema s s reportcmd appendtoresult s define $def lappend result [s validate {<doc>unexpected text<e/></doc>}] s delete } set result } {UNEXPECTED_TEXT 1 UNEXPECTED_TEXT 1} test schema-18.17 {unexpected text} { tdom::schema s s reportcmd appendtoresult s define { defelement doc { ref r1 element c ! {} } defpattern r1 { element a ! {} element b ! {} } } set result [list] foreach xml { <doc>unexpected_text</doc> <doc><a/>unexpected_text</doc> <doc><a/><b/>unexpected_text</doc> <doc><a/><b/><c/>unexpected_text</doc> } { lappend result [s validate $xml] } s delete set result } {UNEXPECTED_TEXT MISSING_ELEMENT 1 UNEXPECTED_TEXT MISSING_ELEMENT 1 UNEXPECTED_TEXT MISSING_ELEMENT 1 UNEXPECTED_TEXT 1} proc schema-18.18 {scmd errortype} { lappend ::result $errortype lappend ::result [$scmd info expected] } test schema-18.18 {missing element at MATCH_ELEMENT_END} { set defs { { defelement doc { ref r1 } defpattern r1 { element a ! {} element b ! {} } } { defelement doc { element a 1 {} element b 1 {} } } { defelement doc { element a0 ! {} ref r1 } defpattern r1 { element a ! {} element b ! {} } } { defelement doc { element a0 ! {} ref r1 element b0 ! {} } defpattern r1 { element a ! {} element b ! {} } } } set result [list] foreach def $defs { tdom::schema s s reportcmd schema-18.18 s define $def lappend result [s validate {<doc/>}] s delete } set result } {MISSING_ELEMENT a 1 MISSING_ELEMENT a 1 MISSING_ELEMENT a0 1 MISSING_ELEMENT a0 1} test schema-18.19 {unexpected text} { tdom::schema s s reportcmd appendtoresult s define { defelement doc { ref r1 ? element c ? {} } defpattern r1 { element a ? {} element b ? {} } } set result [list] foreach xml { <doc>unexpected_text<c/></doc> <doc>unexpected_text<a/><c/></doc> <doc><a/>unexpected_text<c/></doc> <doc><a/>unexpected_text<b/><c/></doc> <doc><a/><b/>unexpected_text<c/></doc> <doc><a/><b/><c/>unexpected_text</doc> } { lappend result [s validate $xml] } s delete set result } {UNEXPECTED_TEXT 1 UNEXPECTED_TEXT 1 UNEXPECTED_TEXT 1 UNEXPECTED_TEXT 1 UNEXPECTED_TEXT 1 UNEXPECTED_TEXT 1} test schema-18.20 {Missing element on element end} { tdom::schema s s reportcmd appendtoresult s define { defelement doc { element a * { element b ! {} element c ! {} } } } set result [list] foreach xml { <doc/> <doc></doc> <doc><a/></doc> <doc><a>unexpected_text</a></doc> <doc><a><b/>unexpected_text</a></doc> <doc><a><b/></a></doc> <doc><a><b/></a><a/></doc> <doc><a><b/></a><a><b/><c/></a><a><b/><c/>unexpected</a></doc> } { lappend result [s validate $xml] } s delete set result } {1 1 MISSING_ELEMENT 1 UNEXPECTED_TEXT MISSING_ELEMENT 1 UNEXPECTED_TEXT MISSING_ELEMENT 1 MISSING_ELEMENT 1 MISSING_ELEMENT MISSING_ELEMENT 1 MISSING_ELEMENT UNEXPECTED_TEXT 1} proc validatedSAX {g xml {keepEmpties 1}} { set args [list -validateCmd $g] if {!$keepEmpties} { lappend args -ignorewhitespace 1 } xml::parser p {*}$args set rc [catch {p parse $xml} errMsg] |
︙ | ︙ |