Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Scripted XPath functions now also work in domunique/domxpathboolean XPath expression arguments.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | schema
Files: files | file ages | folders
SHA3-256: 6c38650608e0a0de106a06c3d1caa589dc05d6078ba17b8c376a3124da6b9437
User & Date: rolf 2020-05-30 01:38:14
Context
2020-06-11
00:52
Merged from trunk. check-in: f782953f52 user: rolf tags: schema
2020-05-30
01:38
Scripted XPath functions now also work in domunique/domxpathboolean XPath expression arguments. check-in: 6c38650608 user: rolf tags: schema
01:04
Scripted XPath functions in domunique/domxpathboolean XPath expression crashes. check-in: ad809ed898 user: rolf tags: schema
Changes

Changes to generic/domxpath.c.

5260
5261
5262
5263
5264
5265
5266

5267
5268
5269
5270
5271
5272
5273
....
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292


int
xpathEvalAst (
    ast             t,
    xpathResultSet *nodeList,
    domNode        *node,

    xpathResultSet *rs,
    char          **errMsg
    )
{
    int i, rc, first = 1, docOrder = 1;
    xpathResultSet savedContext;
    savedContext = *nodeList;
................................................................................
        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) {







>







 







|







5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
....
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293


int
xpathEvalAst (
    ast             t,
    xpathResultSet *nodeList,
    domNode        *node,
    xpathCBs       * cbs,
    xpathResultSet *rs,
    char          **errMsg
    )
{
    int i, rc, first = 1, docOrder = 1;
    xpathResultSet savedContext;
    savedContext = *nodeList;
................................................................................
        if (t->type == Pred) {
            *errMsg = "Pred step not expected now!";
            return XPATH_EVAL_ERR;
        }
        if (first) {
            rc = xpathEvalStepAndPredicates (t, nodeList, node,
                                             node, 0, &docOrder,
                                             cbs, 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) {

Changes to generic/domxpath.h.

169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
...
206
207
208
209
210
211
212















213
214
215
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,
................................................................................
void rsSetString    ( xpathResultSet *rs, const char  *s    );
void rsAddNode      ( xpathResultSet *rs, domNode     *node );
void rsAddNodeFast  ( xpathResultSet *rs, domNode     *node );
void rsCopy         ( xpathResultSet *to, xpathResultSet *from );

/* This function is only used for debugging code */
void rsPrint        ( xpathResultSet *rs );
















#endif








|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
...
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
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,
                     xpathCBs *cbs, 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,
................................................................................
void rsSetString    ( xpathResultSet *rs, const char  *s    );
void rsAddNode      ( xpathResultSet *rs, domNode     *node );
void rsAddNodeFast  ( xpathResultSet *rs, domNode     *node );
void rsCopy         ( xpathResultSet *to, xpathResultSet *from );

/* This function is only used for debugging code */
void rsPrint        ( xpathResultSet *rs );

/* This function is used (outside of tcldom.c) only by schema.c. It
 * has to have a prototype somewhere. */
int tcldom_xpathFuncCallBack (
    void            *clientData,
    char            *functionName,
    domNode         *ctxNode,
    int              position,
    xpathResultSet  *nodeList,
    domNode         *exprContext,
    int              argc,
    xpathResultSets *args,
    xpathResultSet  *result,
    char           **errMsg
    );

#endif

Changes to generic/schema.c.

3175
3176
3177
3178
3179
3180
3181

3182
3183
3184
3185
3186
3187
3188
3189
3190
3191




3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
....
3219
3220
3221
3222
3223
3224
3225
3226

3227
3228
3229
3230
3231
3232
3233
....
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
....
3348
3349
3350
3351
3352
3353
3354
3355

3356
3357
3358
3359
3360
3361
3362
    domKeyConstraint *kc;
    domNode *n;
    domAttrNode *attr;
    int rc, i, j, hnew, len, skip, first;
    char *errMsg = NULL, *keystr, *efsv;
    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);
    xpathRSReset (&nodeList, node);




    while (kc) {
        xpathRSReset (&rs, NULL);
        rc = xpathEvalAst (kc->selector, &nodeList, node, &rs, &errMsg);
        if (rc) {
            SetResult (errMsg);
            goto errorCleanup;
        }
        if (kc->flags & DKC_FLAG_BOOLEAN) {
            i = xpathFuncBoolean (&rs);
            if (!i) {
................................................................................
            if (n->nodeType != ELEMENT_NODE) {
                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) {
                    SetResult (errMsg);
                    goto errorCleanup;
                }
                if (frs.type != xNodeSetResult && frs.type != EmptyResult) {
                    SetResult ("INVALID_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) {
                        SetResult (errMsg);
                        goto errorCleanup;
                    }
                    if (frs.type != xNodeSetResult
                        && frs.type != EmptyResult) {
                        SetResult ("INVALID_DOM_KEYCONSTRAINT");
................................................................................
                        FREE (keystr);
                    }
                }
                if (skip) break;
                Tcl_CreateHashEntry (&htable, Tcl_DStringValue (&dStr), &hnew);
                if (!hnew) {
                    if (recover (interp, sdata, DOM_KEYCONSTRAINT, 
                                 kc->name,NULL, Tcl_DStringValue (&dStr), 0)) {

                        break;
                    }
                    SetResultV ("DOM_KEYCONSTRAINT");
                    goto errorCleanup;
                }
            }
        }







>










>
>
>
>


|







 







|
>







 







|
|







 







|
>







3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
....
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
....
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
....
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
    domKeyConstraint *kc;
    domNode *n;
    domAttrNode *attr;
    int rc, i, j, hnew, len, skip, first;
    char *errMsg = NULL, *keystr, *efsv;
    Tcl_HashTable htable;
    Tcl_DString dStr;
    xpathCBs cbs;

    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);
    xpathRSReset (&nodeList, node);
    cbs.funcCB         = tcldom_xpathFuncCallBack;
    cbs.funcClientData = interp;
    cbs.varCB          = NULL;
    cbs.varClientData  = NULL;
    while (kc) {
        xpathRSReset (&rs, NULL);
        rc = xpathEvalAst (kc->selector, &nodeList, node, &cbs, &rs, &errMsg);
        if (rc) {
            SetResult (errMsg);
            goto errorCleanup;
        }
        if (kc->flags & DKC_FLAG_BOOLEAN) {
            i = xpathFuncBoolean (&rs);
            if (!i) {
................................................................................
            if (n->nodeType != ELEMENT_NODE) {
                SetResult ("INVALID_DOM_KEYCONSTRAINT");
                goto errorCleanup;
            }
            xpathRSReset (&nodeList, n);
            if (kc->nrFields == 1) {
                xpathRSReset (&frs, NULL);
                rc = xpathEvalAst (kc->fields[0], &nodeList, n, &cbs, &frs,
                                   &errMsg);
                if (rc) {
                    SetResult (errMsg);
                    goto errorCleanup;
                }
                if (frs.type != xNodeSetResult && frs.type != EmptyResult) {
                    SetResult ("INVALID_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, &cbs,
                                       &frs, &errMsg);
                    if (rc) {
                        SetResult (errMsg);
                        goto errorCleanup;
                    }
                    if (frs.type != xNodeSetResult
                        && frs.type != EmptyResult) {
                        SetResult ("INVALID_DOM_KEYCONSTRAINT");
................................................................................
                        FREE (keystr);
                    }
                }
                if (skip) break;
                Tcl_CreateHashEntry (&htable, Tcl_DStringValue (&dStr), &hnew);
                if (!hnew) {
                    if (recover (interp, sdata, DOM_KEYCONSTRAINT, 
                                 kc->name, NULL, Tcl_DStringValue (&dStr),
                                 0)) {
                        break;
                    }
                    SetResultV ("DOM_KEYCONSTRAINT");
                    goto errorCleanup;
                }
            }
        }

Changes to generic/tcldom.c.

1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
}


/*----------------------------------------------------------------------------
|   tcldom_xpathFuncCallBack
|
\---------------------------------------------------------------------------*/
static
int tcldom_xpathFuncCallBack (
    void            *clientData,
    char            *functionName,
    domNode         *ctxNode,
    int              position,
    xpathResultSet  *nodeList,
    domNode         *exprContext,







<







1376
1377
1378
1379
1380
1381
1382

1383
1384
1385
1386
1387
1388
1389
}


/*----------------------------------------------------------------------------
|   tcldom_xpathFuncCallBack
|
\---------------------------------------------------------------------------*/

int tcldom_xpathFuncCallBack (
    void            *clientData,
    char            *functionName,
    domNode         *ctxNode,
    int              position,
    xpathResultSet  *nodeList,
    domNode         *exprContext,

Changes to tests/schema.test.

9282
9283
9284
9285
9286
9287
9288



9289
9290

9291
9292
9293
9294
9295
9296
9297
9298
9299
9300

9301
9302


9303
9304
9305
9306
9307
9308
9309
    }
    lassign $args arg1Typ arg1Value arg2Typ arg2Value
    set arg1 [::dom::xpathFuncHelper::coerce2string $arg1Typ $arg1Value]
    set arg2 [::dom::xpathFuncHelper::coerce2string $arg2Typ $arg2Value]
    return [list number [string compare $arg1 $arg2]]
}




test schema-25.6 {domxpathboolean - scripted XPath function} {
    tdom::schema s

    s define {
        defelement doc {
            element a ! {
                text
                domxpathboolean {compare('foo','bar') < 0} first
                domxpathboolean {compare('foo','bar') > 0} second
            }
        }
    }
    set doc [dom parse {<doc><a>2020-07-30</a></doc>}]

    set result [s domvalidate $doc error]
} {0}



proc schema-26.1 {scmd} {
    lappend ::result "fromtcl: [[$scmd info domNode] nodeName]"
}

test schema-26.1 {info domNode} {
    tdom::schema s







>
>
>


>




|
|




>
|
<
>
>







9282
9283
9284
9285
9286
9287
9288
9289
9290
9291
9292
9293
9294
9295
9296
9297
9298
9299
9300
9301
9302
9303
9304
9305
9306

9307
9308
9309
9310
9311
9312
9313
9314
9315
    }
    lassign $args arg1Typ arg1Value arg2Typ arg2Value
    set arg1 [::dom::xpathFuncHelper::coerce2string $arg1Typ $arg1Value]
    set arg2 [::dom::xpathFuncHelper::coerce2string $arg2Typ $arg2Value]
    return [list number [string compare $arg1 $arg2]]
}

proc schema-25.6 {scmd errorType} {
    lappend ::result $errorType [$scmd info vaction name]
}
test schema-25.6 {domxpathboolean - scripted XPath function} {
    tdom::schema s
    s reportcmd schema-25.6
    s define {
        defelement doc {
            element a ! {
                text
                domxpathboolean {compare('foo','bar') > 0} first
                domxpathboolean {compare('foo','bar') < 0} second
            }
        }
    }
    set doc [dom parse {<doc><a>2020-07-30</a></doc>}]
    set result ""
    lappend result [s domvalidate $doc]

    set result
} {DOM_XPATH_BOOLEAN second 1}

proc schema-26.1 {scmd} {
    lappend ::result "fromtcl: [[$scmd info domNode] nodeName]"
}

test schema-26.1 {info domNode} {
    tdom::schema s