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

Changes In Branch tdomNodeType Excluding Merge-Ins

This is equivalent to a diff from 12ce2296e4 to 7148e12240

2014-01-10
01:11
Improved speed of operations in node token mode notable. This is achieved by introducing a Tcl_Obj type tdomNodeType. Tcl_Objs of type tdomNodeType are created without string representation, saving malloc costs until string representation is needed (which typically isn't needed). Additionally, DOM node identification from token is faster with tdomNodeType Tcl_Objs. check-in: 8f70a39a92 user: rolf tags: trunk
2014-01-01
22:08
Enhanced bench suite. Closed-Leaf check-in: 7148e12240 user: rolf tags: tdomNodeType
04:03
Made tcldom_returnNodeOjb static. check-in: 40b95f4a60 user: rolf tags: tdomNodeType
2013-12-29
01:29
Update from trunk. check-in: 6b6f0a48b7 user: rolf tags: tdomNodeType
01:25
Minor test suite correction and addition. check-in: 12ce2296e4 user: rolf tags: trunk
2013-12-27
21:56
More #ifdefery, to handle tip 388 changes to tcl.h. check-in: ebe56a3001 user: rolf tags: trunk

Changes to generic/tcldom.c.

355
356
357
358
359
360
361












362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
\---------------------------------------------------------------------------*/

typedef struct XsltMsgCBInfo {
    Tcl_Interp * interp;
    Tcl_Obj    * msgcmd;
} XsltMsgCBInfo;













/*----------------------------------------------------------------------------
|   Prototypes for procedures defined later in this file:
|
\---------------------------------------------------------------------------*/

static Tcl_VarTraceProc  tcldom_docTrace;
static Tcl_VarTraceProc  tcldom_nodeTrace;

static Tcl_CmdDeleteProc tcldom_docCmdDeleteProc;
static Tcl_CmdDeleteProc tcldom_nodeCmdDeleteProc;

#ifdef TCL_THREADS

static int tcldom_EvalLocked(Tcl_Interp* interp, Tcl_Obj** objv,
                             domDocument* doc, int flag);

static int tcldom_RegisterDocShared(domDocument* doc);







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






<


<







355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379

380
381

382
383
384
385
386
387
388
\---------------------------------------------------------------------------*/

typedef struct XsltMsgCBInfo {
    Tcl_Interp * interp;
    Tcl_Obj    * msgcmd;
} XsltMsgCBInfo;


static void UpdateStringOfTdomNode(Tcl_Obj *objPtr);
static int  SetTdomNodeFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);

const Tcl_ObjType tdomNodeType = {
    "tdom-node",
    NULL,
    NULL,
    UpdateStringOfTdomNode,
    SetTdomNodeFromAny
};

/*----------------------------------------------------------------------------
|   Prototypes for procedures defined later in this file:
|
\---------------------------------------------------------------------------*/

static Tcl_VarTraceProc  tcldom_docTrace;


static Tcl_CmdDeleteProc tcldom_docCmdDeleteProc;


#ifdef TCL_THREADS

static int tcldom_EvalLocked(Tcl_Interp* interp, Tcl_Obj** objv,
                             domDocument* doc, int flag);

static int tcldom_RegisterDocShared(domDocument* doc);
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
    }

    tcldom_deleteDoc(dinfo->interp, doc);

    FREE((void*)dinfo);
}


/*----------------------------------------------------------------------------
|   tcldom_nodeCmdDeleteProc
|
\---------------------------------------------------------------------------*/
static
void tcldom_nodeCmdDeleteProc (
    ClientData  clientData
)
{
    domDeleteInfo *dinfo = (domDeleteInfo *)clientData;
    char          *var   = dinfo->traceVarName;

    DBG(fprintf (stderr, "--> tcldom_nodeCmdDeleteProc node %p\n", 
                 dinfo->node));

    if (var) {
         DBG(fprintf(stderr, "--> tcldom_nodeCmdDeleteProc calls "
                    "Tcl_UntraceVar for \"%s\"\n", var));
        Tcl_UntraceVar(dinfo->interp, var, 
                       TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
                       tcldom_nodeTrace, clientData);
        FREE(var);
        dinfo->traceVarName = NULL;
    }
    FREE((void*)dinfo);
}


/*----------------------------------------------------------------------------
|   tcldom_docTrace
|
\---------------------------------------------------------------------------*/
static
char * tcldom_docTrace (
    ClientData    clientData,







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







491
492
493
494
495
496
497





























498
499
500
501
502
503
504
    }

    tcldom_deleteDoc(dinfo->interp, doc);

    FREE((void*)dinfo);
}






























/*----------------------------------------------------------------------------
|   tcldom_docTrace
|
\---------------------------------------------------------------------------*/
static
char * tcldom_docTrace (
    ClientData    clientData,
544
545
546
547
548
549
550


551
552






553









554
555
556
557
558
559


560
561
562
563



564
565
566
567



568


569



570



571

572
573
574
575
576
577
578
579
580
581
582
583
584


585
586


587

588
589
590
591
592
593
594
595
        DBG(fprintf(stderr, "--> tcldom_docTrace delete doc %p\n", doc));
        Tcl_DeleteCommand(interp, objCmdName);
    }

    return NULL;
}




/*----------------------------------------------------------------------------






|   tcldom_nodeTrace









|
\---------------------------------------------------------------------------*/
static
char * tcldom_nodeTrace (
    ClientData    clientData,
    Tcl_Interp   *interp,


    CONST84 char *name1,
    CONST84 char *name2,
    int           flags
)



{
    domDeleteInfo *dinfo = (domDeleteInfo*)clientData;
    domNode       *node = dinfo->node;
    char           objCmdName[80];






    DBG(fprintf(stderr, "--> tcldom_nodeTrace %x %p\n", flags, node));







    if (flags & TCL_INTERP_DESTROYED) {

        return NULL;
    }
    if (flags & TCL_TRACE_WRITES) {
        return "var is read-only";
    }
    if (flags & TCL_TRACE_UNSETS) {
        NODE_CMD(objCmdName, node);
        DBG(fprintf(stderr, "--> tcldom_nodeTrace delete node %p\n", node));
        Tcl_UntraceVar(interp, name1, TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
                       tcldom_nodeTrace, clientData);
        Tcl_DeleteCommand(interp, objCmdName);
        node->nodeFlags &= ~VISIBLE_IN_TCL;
    }



    return NULL;


}



/*----------------------------------------------------------------------------
|   tcldom_createNodeObj
|
\---------------------------------------------------------------------------*/
void tcldom_createNodeObj (
    Tcl_Interp * interp,







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


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

>
>
|
<
>
>
|
>
|







525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555

556
557
558
559
560
561
562
563
564
565
566

567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586


587




588


589
590
591
592

593
594
595
596
597
598
599
600
601
602
603
604
        DBG(fprintf(stderr, "--> tcldom_docTrace delete doc %p\n", doc));
        Tcl_DeleteCommand(interp, objCmdName);
    }

    return NULL;
}

/*----------------------------------------------------------------------------
|   UpdateStringOfTdomNode
|
\---------------------------------------------------------------------------*/
static void
UpdateStringOfTdomNode(
    Tcl_Obj *objPtr)
{
    char nodeName[80];
    int  len;
    
    NODE_CMD(nodeName, objPtr->internalRep.otherValuePtr);
    len = strlen(nodeName);
    objPtr->bytes = (ckalloc((unsigned char) len+1));
    memcpy(objPtr->bytes, nodeName, len+1);
    objPtr->length = len;
}

/*----------------------------------------------------------------------------
|   SetTdomNodeFromAny
|
\---------------------------------------------------------------------------*/
static int
SetTdomNodeFromAny(

    Tcl_Interp *interp,		/* Tcl interpreter or NULL */
    Tcl_Obj *objPtr)		/* Pointer to the object to parse */
{
    Tcl_CmdInfo  cmdInfo;
    domNode     *node = NULL;
    char        *nodeName;
    
    if (objPtr->typePtr == &tdomNodeType) {
        return TCL_OK;
    }


    nodeName = Tcl_GetString(objPtr);
    if (strncmp(nodeName, "domNode", 7)) {
        if (interp) {
            SetResult("parameter not a domNode!");
            return TCL_ERROR;
        }
    }
    if (sscanf(&nodeName[7], "%p", &node) != 1) {
        if (!Tcl_GetCommandInfo(interp, nodeName, &cmdInfo)) {
            if (interp) {
                SetResult("parameter not a domNode!");
                return TCL_ERROR;
            }
        }
        if (   (cmdInfo.isNativeObjectProc == 0)
            || (cmdInfo.objProc != (Tcl_ObjCmdProc*)tcldom_NodeObjCmd)) {
            if (interp) {
                SetResult("parameter not a domNode object command");
                return TCL_ERROR;
            }


        }




        node = (domNode*)cmdInfo.objClientData;


    }
    if (objPtr->typePtr && objPtr->typePtr->freeIntRepProc) {
        objPtr->typePtr->freeIntRepProc(objPtr);
    }

    objPtr->internalRep.otherValuePtr = node;
    objPtr->typePtr = &tdomNodeType;
    
    return TCL_OK;
}

/*----------------------------------------------------------------------------
|   tcldom_createNodeObj
|
\---------------------------------------------------------------------------*/
void tcldom_createNodeObj (
    Tcl_Interp * interp,
609
610
611
612
613
614
615
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

642
643
644
645
646
647

648






649

650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676




























677
678
679
680
681
682
683
                             (ClientData)        node,
                             (Tcl_CmdDeleteProc*)NULL);
        node->nodeFlags |= VISIBLE_IN_TCL;
    }
}

/*----------------------------------------------------------------------------
|   tcldom_returnNodeObj
|
\---------------------------------------------------------------------------*/
static
int tcldom_returnNodeObj (
    Tcl_Interp *interp,
    domNode    *node,
    int         setVariable,
    Tcl_Obj    *var_name
)
{
    char            objCmdName[80], *objVar;
    domDeleteInfo * dinfo;
    Tcl_CmdInfo     cmdInfo;

    GetTcldomTSD()

    if (node == NULL) {
        if (setVariable) {
            objVar = Tcl_GetString(var_name);
            Tcl_UnsetVar(interp, objVar, 0);
            Tcl_SetVar(interp, objVar, "", 0);
        }
        SetResult("");
        return TCL_OK;
    }

    tcldom_createNodeObj(interp, node, objCmdName);
    if (TSD(dontCreateObjCommands)) {
        if (setVariable) {
            objVar = Tcl_GetString(var_name);
            Tcl_SetVar(interp, objVar, objCmdName, 0);
        }

    } else {






        if (setVariable) {

            objVar = Tcl_GetString(var_name);
            Tcl_UnsetVar(interp, objVar, 0);
            Tcl_SetVar  (interp, objVar, objCmdName, 0);
            Tcl_GetCommandInfo(interp, objCmdName, &cmdInfo);
            if (0) {
                dinfo = (domDeleteInfo*)MALLOC(sizeof(domDeleteInfo));
                dinfo->interp       = interp;
                dinfo->node         = node;
                dinfo->traceVarName = NULL;
                Tcl_TraceVar(interp, objVar, 
                             TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
                             (Tcl_VarTraceProc*)tcldom_nodeTrace,
                             (ClientData)dinfo);
                dinfo->traceVarName = tdomstrdup(objVar);

                /* Patch node object command to remove above trace 
                   on teardown */
                cmdInfo.deleteData = (ClientData)dinfo;
                cmdInfo.deleteProc = tcldom_nodeCmdDeleteProc;
                Tcl_SetCommandInfo(interp, objCmdName, &cmdInfo);
            }
        }
    }

    SetResult(objCmdName);
    return TCL_OK;
}





























/*----------------------------------------------------------------------------
|   tcldom_returnDocumentObj
|
\---------------------------------------------------------------------------*/
int tcldom_returnDocumentObj (
    Tcl_Interp  *interp,







|



|






|
<
|
|





<





>
|
<


|

>

>
>
>
>
>
>

>

<

<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
|
<
<
<
<


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







618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636

637
638
639
640
641
642
643

644
645
646
647
648
649
650

651
652
653
654
655
656
657
658
659
660
661
662
663
664
665

666











667





668




669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
                             (ClientData)        node,
                             (Tcl_CmdDeleteProc*)NULL);
        node->nodeFlags |= VISIBLE_IN_TCL;
    }
}

/*----------------------------------------------------------------------------
|   tcldom_setInterpAndReturnVar
|
\---------------------------------------------------------------------------*/
static
int tcldom_setInterpAndReturnVar (
    Tcl_Interp *interp,
    domNode    *node,
    int         setVariable,
    Tcl_Obj    *var_name
)
{
    char     objCmdName[80], *objVar;

    Tcl_Obj *resultObj;
    
    GetTcldomTSD()

    if (node == NULL) {
        if (setVariable) {
            objVar = Tcl_GetString(var_name);

            Tcl_SetVar(interp, objVar, "", 0);
        }
        SetResult("");
        return TCL_OK;
    }
    if (TSD(dontCreateObjCommands) == 0) {
        tcldom_createNodeObj(interp, node, objCmdName);

        if (setVariable) {
            objVar = Tcl_GetString(var_name);
            Tcl_SetVar  (interp, objVar, objCmdName, 0);
        }
        SetResult(objCmdName);
    } else {
        resultObj = Tcl_NewObj();
        resultObj->bytes = NULL;
        resultObj->length = 0;
        resultObj->internalRep.otherValuePtr = node;
        resultObj->typePtr = &tdomNodeType;
        Tcl_SetObjResult (interp, resultObj);
        if (setVariable) {
            NODE_CMD(objCmdName, node);
            objVar = Tcl_GetString(var_name);

            Tcl_SetVar  (interp, objVar, objCmdName, 0);











        }





    }




    return TCL_OK;
}

/*----------------------------------------------------------------------------
|   tcldom_returnNodeObj
|
\---------------------------------------------------------------------------*/
static
Tcl_Obj *tcldom_returnNodeObj (
    Tcl_Interp *interp,
    domNode    *node)
{
    char     objCmdName[80];
    Tcl_Obj *resultObj;
    
    GetTcldomTSD()

    resultObj = Tcl_NewObj();
    if (node == NULL) {
        return resultObj;
    }
    if (TSD(dontCreateObjCommands) == 0) {
        tcldom_createNodeObj(interp, node, objCmdName);
    }
    resultObj->bytes = NULL;
    resultObj->length = 0;
    resultObj->internalRep.otherValuePtr = node;
    resultObj->typePtr = &tdomNodeType;
    return resultObj;
}

/*----------------------------------------------------------------------------
|   tcldom_returnDocumentObj
|
\---------------------------------------------------------------------------*/
int tcldom_returnDocumentObj (
    Tcl_Interp  *interp,
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
    domNode    *node,
    int         nsIndex,
    const char *uri
)
{
    int         result;
    domNode    *child;
    char        prefix[MAX_PREFIX_LEN], objCmdName[80];
    const char *localName;
    Tcl_Obj    *namePtr, *resultPtr;

    /* nsIndex == -1 ==> DOM 1 no NS i.e getElementsByTagName
       nsIndex != -1 are the NS aware cases
       nsIndex == -2 ==> more than one namespace in the document with the 
                         requested namespace, we have to strcmp the URI







|







779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
    domNode    *node,
    int         nsIndex,
    const char *uri
)
{
    int         result;
    domNode    *child;
    char        prefix[MAX_PREFIX_LEN];
    const char *localName;
    Tcl_Obj    *namePtr, *resultPtr;

    /* nsIndex == -1 ==> DOM 1 no NS i.e getElementsByTagName
       nsIndex != -1 are the NS aware cases
       nsIndex == -2 ==> more than one namespace in the document with the 
                         requested namespace, we have to strcmp the URI
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
            if (nsIndex == -1) {
                localName = node->nodeName;
            } else {
                domSplitQName(node->nodeName, prefix, &localName);
            }
            if (Tcl_StringMatch(localName, namePattern)) {
                resultPtr = Tcl_GetObjResult(interp);
                tcldom_createNodeObj(interp, node, objCmdName);
                namePtr = Tcl_NewStringObj(objCmdName, -1);
                result = Tcl_ListObjAppendElement(interp, resultPtr, namePtr);
                if (result != TCL_OK) {
                    Tcl_DecrRefCount(namePtr);
                    return result;
                }
            }
        }







|
<







814
815
816
817
818
819
820
821

822
823
824
825
826
827
828
            if (nsIndex == -1) {
                localName = node->nodeName;
            } else {
                domSplitQName(node->nodeName, prefix, &localName);
            }
            if (Tcl_StringMatch(localName, namePattern)) {
                resultPtr = Tcl_GetObjResult(interp);
                namePtr = tcldom_returnNodeObj(interp, node);

                result = Tcl_ListObjAppendElement(interp, resultPtr, namePtr);
                if (result != TCL_OK) {
                    Tcl_DecrRefCount(namePtr);
                    return result;
                }
            }
        }
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
    domNode    * node,
    void       * clientData
)
{
    Tcl_Interp * interp = (Tcl_Interp*)clientData;
    Tcl_Obj    * resultPtr = Tcl_GetObjResult(interp);
    Tcl_Obj    * namePtr;
    char         objCmdName[80];
    int          result;


    tcldom_createNodeObj(interp, node, objCmdName);
    namePtr = Tcl_NewStringObj(objCmdName, -1);
    result  = Tcl_ListObjAppendElement(interp, resultPtr, namePtr);
    if (result != TCL_OK) {
        Tcl_DecrRefCount(namePtr);
    }
    return result;
}








<



|
<







890
891
892
893
894
895
896

897
898
899
900

901
902
903
904
905
906
907
    domNode    * node,
    void       * clientData
)
{
    Tcl_Interp * interp = (Tcl_Interp*)clientData;
    Tcl_Obj    * resultPtr = Tcl_GetObjResult(interp);
    Tcl_Obj    * namePtr;

    int          result;


    namePtr = tcldom_returnNodeObj(interp, node);

    result  = Tcl_ListObjAppendElement(interp, resultPtr, namePtr);
    if (result != TCL_OK) {
        Tcl_DecrRefCount(namePtr);
    }
    return result;
}

987
988
989
990
991
992
993















































994
995
996
997
998
999
1000
    }
    if (result != 0) {
        return TCL_ERROR;
    }
    return TCL_OK;
}

















































/*----------------------------------------------------------------------------
|   tcldom_getNodeFromName
|
\---------------------------------------------------------------------------*/
domNode * tcldom_getNodeFromName (
    Tcl_Interp  *interp,







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







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
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
    }
    if (result != 0) {
        return TCL_ERROR;
    }
    return TCL_OK;
}


/*----------------------------------------------------------------------------
|   tcldom_getNodeFromObj
|
\---------------------------------------------------------------------------*/
domNode * tcldom_getNodeFromObj (
    Tcl_Interp  *interp,
    Tcl_Obj     *nodeObj
)
{
    Tcl_CmdInfo  cmdInfo;
    domNode     *node = NULL;
    char        *nodeName;
    
    GetTcldomTSD()

    if (nodeObj->typePtr == &tdomNodeType) {
        return (domNode*)nodeObj->internalRep.otherValuePtr;
    }
    
    if (TSD(dontCreateObjCommands)) {
        if (SetTdomNodeFromAny (interp, nodeObj) == TCL_OK) {
            return (domNode*)nodeObj->internalRep.otherValuePtr;
        }
        return NULL;
    }
    
    nodeName = Tcl_GetString(nodeObj);
    if (strncmp(nodeName, "domNode", 7)) {
        SetResult("parameter not a domNode!");
        return NULL;
    }
    if (sscanf(&nodeName[7], "%p", &node) != 1) {
        if (!Tcl_GetCommandInfo(interp, nodeName, &cmdInfo)) {
            SetResult("parameter not a domNode!");
            return NULL;
        }
        if (   (cmdInfo.isNativeObjectProc == 0)
            || (cmdInfo.objProc != (Tcl_ObjCmdProc*)tcldom_NodeObjCmd)) {
            SetResult("parameter not a domNode object command!");
            return NULL;
        }
        node = (domNode*)cmdInfo.objClientData;
    }

    return node;
}

/*----------------------------------------------------------------------------
|   tcldom_getNodeFromName
|
\---------------------------------------------------------------------------*/
domNode * tcldom_getNodeFromName (
    Tcl_Interp  *interp,
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
    nodeToAppend = doc->rootNode->firstChild;
    while (nodeToAppend) {
        domAppendChild(node, nodeToAppend);
        nodeToAppend = nodeToAppend->nextSibling;
    }
    domFreeDocument(doc, NULL, NULL);

    return tcldom_returnNodeObj(interp, node, 0, NULL);
#endif
}


/*----------------------------------------------------------------------------
|   tcldom_xpathResultSet
|
\---------------------------------------------------------------------------*/
static
int tcldom_xpathResultSet (
    Tcl_Interp      *interp,
    xpathResultSet  *rs,
    Tcl_Obj         *type,
    Tcl_Obj         *value
)
{
    int          rc, i;
    Tcl_Obj     *namePtr, *objv[2];
    char         objCmdName[80];
    domAttrNode *attr;
    domNodeType  startType;
    int          mixedNodeSet;

    switch (rs->type) {
        case EmptyResult:
             Tcl_SetStringObj(type, "empty", -1);







|


















<







1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248

1249
1250
1251
1252
1253
1254
1255
    nodeToAppend = doc->rootNode->firstChild;
    while (nodeToAppend) {
        domAppendChild(node, nodeToAppend);
        nodeToAppend = nodeToAppend->nextSibling;
    }
    domFreeDocument(doc, NULL, NULL);

    return tcldom_setInterpAndReturnVar(interp, node, 0, NULL);
#endif
}


/*----------------------------------------------------------------------------
|   tcldom_xpathResultSet
|
\---------------------------------------------------------------------------*/
static
int tcldom_xpathResultSet (
    Tcl_Interp      *interp,
    xpathResultSet  *rs,
    Tcl_Obj         *type,
    Tcl_Obj         *value
)
{
    int          rc, i;
    Tcl_Obj     *namePtr, *objv[2];

    domAttrNode *attr;
    domNodeType  startType;
    int          mixedNodeSet;

    switch (rs->type) {
        case EmptyResult:
             Tcl_SetStringObj(type, "empty", -1);
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
                 if (rs->nodes[i]->nodeType == ATTRIBUTE_NODE) {
                     attr = (domAttrNode*)rs->nodes[i];
                     objv[0] = Tcl_NewStringObj(attr->nodeName, -1);
                     objv[1] = Tcl_NewStringObj(attr->nodeValue,
                                                attr->valueLength);
                     namePtr = Tcl_NewListObj(2, objv);
                 } else {
                     tcldom_createNodeObj(interp, rs->nodes[i], objCmdName);
                     namePtr = Tcl_NewStringObj(objCmdName, -1);
                 }
                 rc = Tcl_ListObjAppendElement(interp, value, namePtr);
                 if (rc != TCL_OK) {
                     Tcl_DecrRefCount(namePtr);
                     return rc;
                 }
             }







|
<







1300
1301
1302
1303
1304
1305
1306
1307

1308
1309
1310
1311
1312
1313
1314
                 if (rs->nodes[i]->nodeType == ATTRIBUTE_NODE) {
                     attr = (domAttrNode*)rs->nodes[i];
                     objv[0] = Tcl_NewStringObj(attr->nodeName, -1);
                     objv[1] = Tcl_NewStringObj(attr->nodeValue,
                                                attr->valueLength);
                     namePtr = Tcl_NewListObj(2, objv);
                 } else {
                     namePtr = tcldom_returnNodeObj(interp, rs->nodes[i]);

                 }
                 rc = Tcl_ListObjAppendElement(interp, value, namePtr);
                 if (rc != TCL_OK) {
                     Tcl_DecrRefCount(namePtr);
                     return rc;
                 }
             }
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
    xpathResultSets *args,
    xpathResultSet  *result,
    char           **errMsg
)
{
    Tcl_Interp  *interp = (Tcl_Interp*) clientData;
    char         tclxpathFuncName[200], objCmdName[80];
    char         *errStr, *typeStr, *nodeName;
    Tcl_Obj     *resultPtr, *objv[MAX_REWRITE_ARGS], *type, *value, *nodeObj,
                *tmpObj;
    Tcl_CmdInfo  cmdInfo;
    int          objc, rc, i, errStrLen, listLen, intValue, res;
    double       doubleValue;
    domNode     *node;








|







1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
    xpathResultSets *args,
    xpathResultSet  *result,
    char           **errMsg
)
{
    Tcl_Interp  *interp = (Tcl_Interp*) clientData;
    char         tclxpathFuncName[200], objCmdName[80];
    char         *errStr, *typeStr;
    Tcl_Obj     *resultPtr, *objv[MAX_REWRITE_ARGS], *type, *value, *nodeObj,
                *tmpObj;
    Tcl_CmdInfo  cmdInfo;
    int          objc, rc, i, errStrLen, listLen, intValue, res;
    double       doubleValue;
    domNode     *node;

1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
        tmpObj = Tcl_NewListObj(0, NULL);
        Tcl_ListObjAppendElement(interp, tmpObj, 
                                 Tcl_NewStringObj(objCmdName, -1));
        Tcl_ListObjAppendElement(
            interp, tmpObj,
            Tcl_NewStringObj(((domAttrNode*)ctxNode)->nodeName, -1));
    } else {
        tcldom_createNodeObj(interp, ctxNode, objCmdName);
        tmpObj = Tcl_NewStringObj(objCmdName, -1);
    }
    objv[objc] = tmpObj;
    Tcl_IncrRefCount(objv[objc++]);

    objv[objc] = Tcl_NewIntObj(position);
    Tcl_IncrRefCount(objv[objc++]);








|
<







1385
1386
1387
1388
1389
1390
1391
1392

1393
1394
1395
1396
1397
1398
1399
        tmpObj = Tcl_NewListObj(0, NULL);
        Tcl_ListObjAppendElement(interp, tmpObj, 
                                 Tcl_NewStringObj(objCmdName, -1));
        Tcl_ListObjAppendElement(
            interp, tmpObj,
            Tcl_NewStringObj(((domAttrNode*)ctxNode)->nodeName, -1));
    } else {
        tmpObj = tcldom_returnNodeObj(interp, ctxNode);

    }
    objv[objc] = tmpObj;
    Tcl_IncrRefCount(objv[objc++]);

    objv[objc] = Tcl_NewIntObj(position);
    Tcl_IncrRefCount(objv[objc++]);

1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
                if (rc != TCL_OK) {
                    *errMsg = tdomstrdup("value not a node list!");
                    res = XPATH_EVAL_ERR;
                    goto funcCallCleanup;
                }
                for (i=0; i < listLen; i++) {
                    rc = Tcl_ListObjIndex(interp, value, i, &nodeObj);
                    nodeName = Tcl_GetString(nodeObj);
                    node = tcldom_getNodeFromName(interp, nodeName, &errStr);
                    if (node == NULL) {
                        *errMsg = tdomstrdup(errStr);
                        res = XPATH_EVAL_ERR;
                        goto funcCallCleanup;
                    }
                    rsAddNode(result, node);
                }
                sortByDocOrder(result);
            } else







<
|

|







1455
1456
1457
1458
1459
1460
1461

1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
                if (rc != TCL_OK) {
                    *errMsg = tdomstrdup("value not a node list!");
                    res = XPATH_EVAL_ERR;
                    goto funcCallCleanup;
                }
                for (i=0; i < listLen; i++) {
                    rc = Tcl_ListObjIndex(interp, value, i, &nodeObj);

                    node = tcldom_getNodeFromObj(interp, nodeObj);
                    if (node == NULL) {
                        *errMsg = tdomstrdup(Tcl_GetStringResult(interp));
                        res = XPATH_EVAL_ERR;
                        goto funcCallCleanup;
                    }
                    rsAddNode(result, node);
                }
                sortByDocOrder(result);
            } else
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
            return rc;
        }
        if ((rc = tcldom_appendFromTclList(interp, newnode, childObj))
            != TCL_OK) {
            return rc;
        }
    }
    return tcldom_returnNodeObj(interp, node, 0, NULL);
}


/*----------------------------------------------------------------------------
|   tcldom_treeAsTclList
|
\---------------------------------------------------------------------------*/







|







2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
            return rc;
        }
        if ((rc = tcldom_appendFromTclList(interp, newnode, childObj))
            != TCL_OK) {
            return rc;
        }
    }
    return tcldom_setInterpAndReturnVar(interp, node, 0, NULL);
}


/*----------------------------------------------------------------------------
|   tcldom_treeAsTclList
|
\---------------------------------------------------------------------------*/
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
    domDocument *doc,
    Tcl_Interp  *interp,
    int          objc,
    Tcl_Obj     *CONST objv[] 
    )
{
    int      len, i, hnew;
    char    *errMsg;
    Tcl_HashEntry *h;
    Tcl_Obj *objPtr;
    domNode     *node;
    
    CheckArgs (4,4,0, "<domDoc> renameNode nodeList name");
    if (Tcl_ListObjLength (interp, objv[2], &len) != TCL_OK) {
        SetResult ("The first argument to the renameNode method"
                   " must be a list of element nodes.");
        return TCL_ERROR;
    }
    h = Tcl_CreateHashEntry(&HASHTAB(doc,tdom_tagNames), 
                            Tcl_GetString(objv[3]), &hnew);
    for (i = 0; i < len; i++) {
        Tcl_ListObjIndex (interp, objv[2], i, &objPtr);
        node = tcldom_getNodeFromName (interp, Tcl_GetString (objPtr),
                                       &errMsg);
        if (node == NULL) {
            SetResult (errMsg);
            if (errMsg) FREE (errMsg);
            return TCL_ERROR;
        }
        node->nodeName = (char *)&(h->key);
    }
    return TCL_OK;
}








<














|
<

<
<







3383
3384
3385
3386
3387
3388
3389

3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404

3405


3406
3407
3408
3409
3410
3411
3412
    domDocument *doc,
    Tcl_Interp  *interp,
    int          objc,
    Tcl_Obj     *CONST objv[] 
    )
{
    int      len, i, hnew;

    Tcl_HashEntry *h;
    Tcl_Obj *objPtr;
    domNode     *node;
    
    CheckArgs (4,4,0, "<domDoc> renameNode nodeList name");
    if (Tcl_ListObjLength (interp, objv[2], &len) != TCL_OK) {
        SetResult ("The first argument to the renameNode method"
                   " must be a list of element nodes.");
        return TCL_ERROR;
    }
    h = Tcl_CreateHashEntry(&HASHTAB(doc,tdom_tagNames), 
                            Tcl_GetString(objv[3]), &hnew);
    for (i = 0; i < len; i++) {
        Tcl_ListObjIndex (interp, objv[2], i, &objPtr);
        node = tcldom_getNodeFromObj (interp, objPtr);

        if (node == NULL) {


            return TCL_ERROR;
        }
        node->nodeName = (char *)&(h->key);
    }
    return TCL_OK;
}

3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
{
    GetTcldomTSD()

    domNode     *node, *child, *refChild, *oldChild, *refNode;
    domNS       *ns;
    domAttrNode *attrs;
    domException exception;
    char         tmp[200], objCmdName[80], prefix[MAX_PREFIX_LEN],
                *method, *nodeName, *str, *attr_name, *attr_val, *filter,
                *errMsg;
    const char  *localName, *uri, *nsStr;
    int          result, length, methodIndex, i, line, column;
    int          nsIndex, bool, hnew, legacy;
    Tcl_Obj     *namePtr, *resultPtr;
    Tcl_Obj     *mobjv[MAX_REWRITE_ARGS];
    Tcl_CmdInfo  cmdInfo;
    Tcl_HashEntry *h;







|
|
<







3719
3720
3721
3722
3723
3724
3725
3726
3727

3728
3729
3730
3731
3732
3733
3734
{
    GetTcldomTSD()

    domNode     *node, *child, *refChild, *oldChild, *refNode;
    domNS       *ns;
    domAttrNode *attrs;
    domException exception;
    char         tmp[200], prefix[MAX_PREFIX_LEN], *method, *nodeName,
                 *str, *attr_name, *attr_val, *filter;

    const char  *localName, *uri, *nsStr;
    int          result, length, methodIndex, i, line, column;
    int          nsIndex, bool, hnew, legacy;
    Tcl_Obj     *namePtr, *resultPtr;
    Tcl_Obj     *mobjv[MAX_REWRITE_ARGS];
    Tcl_CmdInfo  cmdInfo;
    Tcl_HashEntry *h;
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
        if (objc < 3) {
            SetResult(node_usage);
            return TCL_ERROR;
        }
        if (TSD(domCreateCmdMode) == DOM_CREATECMDMODE_AUTO) {
            TSD(dontCreateObjCommands) = 1;
        }
        nodeName = Tcl_GetString(objv[1]);
        node = tcldom_getNodeFromName(interp, nodeName, &errMsg);
        if (node == NULL) {
            SetResult(errMsg);
            return TCL_ERROR;
        }
        objc--;
        objv++;
    }
    if (objc < 2) {
        SetResult(node_usage);







<
|

<







3786
3787
3788
3789
3790
3791
3792

3793
3794

3795
3796
3797
3798
3799
3800
3801
        if (objc < 3) {
            SetResult(node_usage);
            return TCL_ERROR;
        }
        if (TSD(domCreateCmdMode) == DOM_CREATECMDMODE_AUTO) {
            TSD(dontCreateObjCommands) = 1;
        }

        node = tcldom_getNodeFromObj(interp, objv[1]);
        if (node == NULL) {

            return TCL_ERROR;
        }
        objc--;
        objv++;
    }
    if (objc < 2) {
        SetResult(node_usage);
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
        case m_selectNodes:
            return tcldom_selectNodes (interp, node, --objc, ++objv);

        case m_find:
            CheckArgs(4,5,2,"attrName attrVal ?nodeObjVar?");
            attr_name = Tcl_GetStringFromObj(objv[2], NULL);
            attr_val  = Tcl_GetStringFromObj(objv[3], &length);
            return tcldom_returnNodeObj
                (interp, tcldom_find(node, attr_name, attr_val, length),
                 (objc == 5), (objc == 5) ? objv[4] : NULL);

        case m_child:
            CheckArgs(3,6,2,"instance|all ?type? ?attr value?");
            return tcldom_xpointerSearch(interp, XP_CHILD, node, objc, objv);








|







3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
        case m_selectNodes:
            return tcldom_selectNodes (interp, node, --objc, ++objv);

        case m_find:
            CheckArgs(4,5,2,"attrName attrVal ?nodeObjVar?");
            attr_name = Tcl_GetStringFromObj(objv[2], NULL);
            attr_val  = Tcl_GetStringFromObj(objv[3], &length);
            return tcldom_setInterpAndReturnVar
                (interp, tcldom_find(node, attr_name, attr_val, length),
                 (objc == 5), (objc == 5) ? objv[4] : NULL);

        case m_child:
            CheckArgs(3,6,2,"instance|all ?type? ?attr value?");
            return tcldom_xpointerSearch(interp, XP_CHILD, node, objc, objv);

3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
            return tcldom_xpointerSearch(interp, XP_PSIBLING, node,objc,objv);

        case m_root:
            CheckArgs(2,3,2,"?nodeObjVar?");
            while (node->parentNode) {
                node = node->parentNode;
            }
            return tcldom_returnNodeObj(interp, node, (objc == 3),
                                        (objc == 3) ? objv[2] : NULL);

        case m_text:
            CheckArgs(2,2,2,"");
            if (node->nodeType != ELEMENT_NODE) {
                SetResult("NOT_AN_ELEMENT");
                return TCL_ERROR;







|







3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
            return tcldom_xpointerSearch(interp, XP_PSIBLING, node,objc,objv);

        case m_root:
            CheckArgs(2,3,2,"?nodeObjVar?");
            while (node->parentNode) {
                node = node->parentNode;
            }
            return tcldom_setInterpAndReturnVar(interp, node, (objc == 3),
                                        (objc == 3) ? objv[2] : NULL);

        case m_text:
            CheckArgs(2,2,2,"");
            if (node->nodeType != ELEMENT_NODE) {
                SetResult("NOT_AN_ELEMENT");
                return TCL_ERROR;
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
            for ( i = 2;  i < objc; ) {
                attr_name = Tcl_GetString(objv[i++]);
                CheckName (interp, attr_name, "attribute", 0);
                attr_val  = Tcl_GetString(objv[i++]);
                CheckText (interp, attr_val, "attribute");
                domSetAttribute(node, attr_name, attr_val);
            }
            return tcldom_returnNodeObj(interp, node, 0, NULL);

        case m_setAttributeNS:
            if (node->nodeType != ELEMENT_NODE) {
                SetResult("NOT_AN_ELEMENT : there are no attributes");
                return TCL_ERROR;
            }
            if ((objc < 5) || (((objc - 2) % 3) != 0)) {







|







4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
            for ( i = 2;  i < objc; ) {
                attr_name = Tcl_GetString(objv[i++]);
                CheckName (interp, attr_name, "attribute", 0);
                attr_val  = Tcl_GetString(objv[i++]);
                CheckText (interp, attr_val, "attribute");
                domSetAttribute(node, attr_name, attr_val);
            }
            return tcldom_setInterpAndReturnVar(interp, node, 0, NULL);

        case m_setAttributeNS:
            if (node->nodeType != ELEMENT_NODE) {
                SetResult("NOT_AN_ELEMENT : there are no attributes");
                return TCL_ERROR;
            }
            if ((objc < 5) || (((objc - 2) % 3) != 0)) {
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
                        SetResult("For all prefixed attributes with prefixes "
                                  "other than 'xml' or 'xmlns' "
                                  "you have to provide a namespace URI");
                    }
                    return TCL_ERROR;
                }
            }
            return tcldom_returnNodeObj(interp, node, 0, NULL);

        case m_hasAttribute:
            CheckArgs(3,3,2,"attrName");
            if (node->nodeType != ELEMENT_NODE) {		
                SetResult("NOT_AN_ELEMENT : there are no attributes");
                return TCL_ERROR;
            }







|







4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
                        SetResult("For all prefixed attributes with prefixes "
                                  "other than 'xml' or 'xmlns' "
                                  "you have to provide a namespace URI");
                    }
                    return TCL_ERROR;
                }
            }
            return tcldom_setInterpAndReturnVar(interp, node, 0, NULL);

        case m_hasAttribute:
            CheckArgs(3,3,2,"attrName");
            if (node->nodeType != ELEMENT_NODE) {		
                SetResult("NOT_AN_ELEMENT : there are no attributes");
                return TCL_ERROR;
            }
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
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198



4199
4200
4201
4202
4203
4204
4205
4206

4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269



4270
4271
4272
4273
4274
4275
4276
4277

4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
            result = domRemoveAttribute(node, attr_name);
            if (result) {
                SetResult("can't remove attribute '");
                AppendResult(attr_name);
                AppendResult("'");
                return TCL_ERROR;
            }
            return tcldom_returnNodeObj(interp, node, 0, NULL);

        case m_removeAttributeNS:
            CheckArgs(4,4,2,"uri attrName");
            if (node->nodeType != ELEMENT_NODE) {		
                SetResult("NOT_AN_ELEMENT : there are no attributes");
                return TCL_ERROR;
            }
            uri = Tcl_GetString(objv[2]);
            localName = Tcl_GetString(objv[3]);
            result = domRemoveAttributeNS(node, uri, localName);
            if (result < 0) {
                SetResult("can't remove attribute with localName '");
                AppendResult(localName);
                AppendResult("'");
                return TCL_ERROR;
            }
            return tcldom_returnNodeObj(interp, node, 0, NULL);

        case m_nextSibling:
            CheckArgs(2,3,2,"?nodeObjVar?");
            return tcldom_returnNodeObj(interp, node->nextSibling,
                                        (objc == 3), 
                                        (objc == 3) ? objv[2] : NULL);
        case m_previousSibling:
            CheckArgs(2,3,2,"?nodeObjVar?");
            return tcldom_returnNodeObj(interp, node->previousSibling,
                                        (objc == 3),
                                        (objc == 3) ? objv[2] : NULL);
        case m_firstChild:
            CheckArgs(2,3,2,"?nodeObjVar?");
            if (node->nodeType == ELEMENT_NODE) {
                return tcldom_returnNodeObj(interp, node->firstChild,
                                            (objc == 3),
                                            (objc == 3) ? objv[2] : NULL);
            }
            return tcldom_returnNodeObj(interp, NULL, (objc == 3),
                                        (objc == 3) ? objv[2] : NULL);
        case m_lastChild:
            CheckArgs(2,3,2,"?nodeObjVar?");
            if (node->nodeType == ELEMENT_NODE) {
                return tcldom_returnNodeObj(interp, node->lastChild,
                                            (objc == 3),
                                            (objc == 3) ? objv[2] : NULL);
            }
            return tcldom_returnNodeObj(interp, NULL, (objc == 3),
                                        (objc == 3) ? objv[2] : NULL);
        case m_parentNode:
            CheckArgs(2,3,2,"?nodeObjVar?");
            return tcldom_returnNodeObj(interp, node->parentNode, (objc == 3),
                                        (objc == 3) ? objv[2] : NULL);
        case m_appendFromList:
            CheckArgs(3,3,2,"list");
            return tcldom_appendFromTclList(interp, node, objv[2]);

        case m_appendFromScript:
            CheckArgs(3,3,2,"script");
            if (nodecmd_appendFromScript(interp, node, objv[2]) != TCL_OK) {
                return TCL_ERROR;
            }
            return tcldom_returnNodeObj(interp, node, 0, NULL);

        case m_insertBeforeFromScript:
            CheckArgs(4,4,2, "script refChild");



            nodeName = Tcl_GetString (objv[3]);
            if (nodeName[0] == '\0') {
                refChild = NULL;
            } else {
                refChild = tcldom_getNodeFromName (interp, nodeName, &errMsg);
                if (refChild == NULL) {
                    SetResult ( errMsg );
                    return TCL_ERROR;

                }
            }
            if (nodecmd_insertBeforeFromScript(interp, node, objv[2], refChild)
                != TCL_OK) {
                return TCL_ERROR;
            }
            return tcldom_returnNodeObj (interp, node, 0, NULL);
            
        case m_appendXML:
            CheckArgs(3,3,2,"xmlString");
            return tcldom_appendXML(interp, node, objv[2]);

        case m_appendChild:
            CheckArgs(3,3,2,"nodeToAppend");
            nodeName = Tcl_GetString(objv[2]);
            child = tcldom_getNodeFromName(interp, nodeName, &errMsg);
            if (child == NULL) {
                SetResult(errMsg);
                return TCL_ERROR;
            }
            exception = domAppendChild (node, child);
            if (exception != OK) {
                SetResult(domException2String(exception));
                return TCL_ERROR;
            }
            return tcldom_returnNodeObj(interp, child, 0, NULL);

        case m_cloneNode:
            CheckArgs(2,3,2,"?-deep?");
            if (objc == 3) {
                if (!strcmp(Tcl_GetString(objv[2]), "-deep")) {
                    return tcldom_returnNodeObj(interp, domCloneNode(node, 1),
                                                0, NULL);
                }
                SetResult("unknown option! Options: ?-deep? ");
                return TCL_ERROR;
            }
            return tcldom_returnNodeObj(interp, domCloneNode(node, 0), 0, NULL);

        case m_removeChild:
            CheckArgs(3,3,2,"childToRemove");
            nodeName = Tcl_GetString(objv[2]);
            child = tcldom_getNodeFromName(interp, nodeName, &errMsg);
            if (child == NULL) {
                SetResult(errMsg);
                return TCL_ERROR;
            }
            exception = domRemoveChild (node, child);
            if (exception != OK) {
                SetResult (domException2String (exception));
                return TCL_ERROR;
            }
            return tcldom_returnNodeObj(interp, child, 0, NULL);

        case m_insertBefore:
            CheckArgs(4,4,2,"childToInsert refChild");
            nodeName = Tcl_GetString(objv[2]);
            child = tcldom_getNodeFromName(interp, nodeName, &errMsg);
            if (child == NULL) {
                SetResult(errMsg);
                return TCL_ERROR;
            }




            nodeName = Tcl_GetString (objv[3]);
            if (nodeName[0] == '\0') {
                refChild = NULL;
            } else {
                refChild = tcldom_getNodeFromName (interp, nodeName, &errMsg);
                if (refChild == NULL) {
                    SetResult ( errMsg );
                    return TCL_ERROR;

                }
            }
            exception = domInsertBefore(node, child, refChild);
            if (exception != OK) {
                SetResult(domException2String(exception));
                return TCL_ERROR;
            }
            return tcldom_returnNodeObj(interp, child, 0, NULL);

        case m_replaceChild:
            CheckArgs(4,4,2,"new old");
            nodeName = Tcl_GetString(objv[2]);
            child = tcldom_getNodeFromName(interp, nodeName, &errMsg);
            if (child == NULL) {
                SetResult(errMsg);
                return TCL_ERROR;
            }

            nodeName = Tcl_GetString(objv[3]);
            oldChild = tcldom_getNodeFromName(interp, nodeName, &errMsg);
            if (oldChild == NULL) {
                SetResult(errMsg);
                return TCL_ERROR;
            }
            exception = domReplaceChild(node, child, oldChild);
            if (exception != OK) {
                SetResult(domException2String(exception));
                return TCL_ERROR;
            }
            return tcldom_returnNodeObj(interp, oldChild, 0, NULL);

        case m_hasChildNodes:
            CheckArgs(2,2,2,"");
            if (node->nodeType == ELEMENT_NODE) {
                SetIntResult(node->firstChild ? 1 : 0);
            } else {
                SetIntResult(0);
            }
            break;

        case m_childNodes:
            CheckArgs(2,2,2,"");
            resultPtr = Tcl_GetObjResult(interp);
            if (node->nodeType == ELEMENT_NODE) {
                child = node->firstChild;
                while (child != NULL) {
                    tcldom_createNodeObj(interp, child, objCmdName);
                    namePtr = Tcl_NewStringObj(objCmdName, -1);
                    result  = Tcl_ListObjAppendElement(interp, resultPtr,
                                                       namePtr);
                    if (result != TCL_OK) {
                        Tcl_DecrRefCount(namePtr);
                        return result;
                    }
                    child = child->nextSibling;







|
















|



|




|





|



|




|



|



|










|



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






|







<
|

<







|





|





|



<
|

<







|



<
|

<



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







|



<
|

<


<
<
|

<







|
















|
<







4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262

4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278

4279
4280

4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303

4304
4305

4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316

4317
4318

4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330

4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343

4344
4345

4346
4347


4348
4349

4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374

4375
4376
4377
4378
4379
4380
4381
            result = domRemoveAttribute(node, attr_name);
            if (result) {
                SetResult("can't remove attribute '");
                AppendResult(attr_name);
                AppendResult("'");
                return TCL_ERROR;
            }
            return tcldom_setInterpAndReturnVar(interp, node, 0, NULL);

        case m_removeAttributeNS:
            CheckArgs(4,4,2,"uri attrName");
            if (node->nodeType != ELEMENT_NODE) {		
                SetResult("NOT_AN_ELEMENT : there are no attributes");
                return TCL_ERROR;
            }
            uri = Tcl_GetString(objv[2]);
            localName = Tcl_GetString(objv[3]);
            result = domRemoveAttributeNS(node, uri, localName);
            if (result < 0) {
                SetResult("can't remove attribute with localName '");
                AppendResult(localName);
                AppendResult("'");
                return TCL_ERROR;
            }
            return tcldom_setInterpAndReturnVar(interp, node, 0, NULL);

        case m_nextSibling:
            CheckArgs(2,3,2,"?nodeObjVar?");
            return tcldom_setInterpAndReturnVar(interp, node->nextSibling,
                                        (objc == 3), 
                                        (objc == 3) ? objv[2] : NULL);
        case m_previousSibling:
            CheckArgs(2,3,2,"?nodeObjVar?");
            return tcldom_setInterpAndReturnVar(interp, node->previousSibling,
                                        (objc == 3),
                                        (objc == 3) ? objv[2] : NULL);
        case m_firstChild:
            CheckArgs(2,3,2,"?nodeObjVar?");
            if (node->nodeType == ELEMENT_NODE) {
                return tcldom_setInterpAndReturnVar(interp, node->firstChild,
                                            (objc == 3),
                                            (objc == 3) ? objv[2] : NULL);
            }
            return tcldom_setInterpAndReturnVar(interp, NULL, (objc == 3),
                                        (objc == 3) ? objv[2] : NULL);
        case m_lastChild:
            CheckArgs(2,3,2,"?nodeObjVar?");
            if (node->nodeType == ELEMENT_NODE) {
                return tcldom_setInterpAndReturnVar(interp, node->lastChild,
                                            (objc == 3),
                                            (objc == 3) ? objv[2] : NULL);
            }
            return tcldom_setInterpAndReturnVar(interp, NULL, (objc == 3),
                                        (objc == 3) ? objv[2] : NULL);
        case m_parentNode:
            CheckArgs(2,3,2,"?nodeObjVar?");
            return tcldom_setInterpAndReturnVar(interp, node->parentNode, (objc == 3),
                                        (objc == 3) ? objv[2] : NULL);
        case m_appendFromList:
            CheckArgs(3,3,2,"list");
            return tcldom_appendFromTclList(interp, node, objv[2]);

        case m_appendFromScript:
            CheckArgs(3,3,2,"script");
            if (nodecmd_appendFromScript(interp, node, objv[2]) != TCL_OK) {
                return TCL_ERROR;
            }
            return tcldom_setInterpAndReturnVar(interp, node, 0, NULL);

        case m_insertBeforeFromScript:
            CheckArgs(4,4,2, "script refChild");
            if (objv[3]->typePtr == &tdomNodeType) {
                refChild = objv[3]->internalRep.otherValuePtr;
            } else {
                nodeName = Tcl_GetString (objv[3]);
                if (nodeName[0] == '\0') {
                    refChild = NULL;
                } else {
                    refChild = tcldom_getNodeFromObj (interp, objv[3]);
                    if (refChild == NULL) {

                        return TCL_ERROR;
                    }
                }
            }
            if (nodecmd_insertBeforeFromScript(interp, node, objv[2], refChild)
                != TCL_OK) {
                return TCL_ERROR;
            }
            return tcldom_setInterpAndReturnVar (interp, node, 0, NULL);
            
        case m_appendXML:
            CheckArgs(3,3,2,"xmlString");
            return tcldom_appendXML(interp, node, objv[2]);

        case m_appendChild:
            CheckArgs(3,3,2,"nodeToAppend");

            child = tcldom_getNodeFromObj(interp, objv[2]);
            if (child == NULL) {

                return TCL_ERROR;
            }
            exception = domAppendChild (node, child);
            if (exception != OK) {
                SetResult(domException2String(exception));
                return TCL_ERROR;
            }
            return tcldom_setInterpAndReturnVar(interp, child, 0, NULL);

        case m_cloneNode:
            CheckArgs(2,3,2,"?-deep?");
            if (objc == 3) {
                if (!strcmp(Tcl_GetString(objv[2]), "-deep")) {
                    return tcldom_setInterpAndReturnVar(interp, domCloneNode(node, 1),
                                                0, NULL);
                }
                SetResult("unknown option! Options: ?-deep? ");
                return TCL_ERROR;
            }
            return tcldom_setInterpAndReturnVar(interp, domCloneNode(node, 0), 0, NULL);

        case m_removeChild:
            CheckArgs(3,3,2,"childToRemove");

            child = tcldom_getNodeFromObj(interp, objv[2]);
            if (child == NULL) {

                return TCL_ERROR;
            }
            exception = domRemoveChild (node, child);
            if (exception != OK) {
                SetResult (domException2String (exception));
                return TCL_ERROR;
            }
            return tcldom_setInterpAndReturnVar(interp, child, 0, NULL);

        case m_insertBefore:
            CheckArgs(4,4,2,"childToInsert refChild");

            child = tcldom_getNodeFromObj(interp, objv[2]);
            if (child == NULL) {

                return TCL_ERROR;
            }

            if (objv[3]->typePtr == &tdomNodeType) {
                refChild = objv[3]->internalRep.otherValuePtr;
            } else {
                nodeName = Tcl_GetString (objv[3]);
                if (nodeName[0] == '\0') {
                    refChild = NULL;
                } else {
                    refChild = tcldom_getNodeFromObj (interp, objv[3]);
                    if (refChild == NULL) {

                        return TCL_ERROR;
                    }
                }
            }
            exception = domInsertBefore(node, child, refChild);
            if (exception != OK) {
                SetResult(domException2String(exception));
                return TCL_ERROR;
            }
            return tcldom_setInterpAndReturnVar(interp, child, 0, NULL);

        case m_replaceChild:
            CheckArgs(4,4,2,"new old");

            child = tcldom_getNodeFromObj(interp, objv[2]);
            if (child == NULL) {

                return TCL_ERROR;
            }


            oldChild = tcldom_getNodeFromObj(interp, objv[3]);
            if (oldChild == NULL) {

                return TCL_ERROR;
            }
            exception = domReplaceChild(node, child, oldChild);
            if (exception != OK) {
                SetResult(domException2String(exception));
                return TCL_ERROR;
            }
            return tcldom_setInterpAndReturnVar(interp, oldChild, 0, NULL);

        case m_hasChildNodes:
            CheckArgs(2,2,2,"");
            if (node->nodeType == ELEMENT_NODE) {
                SetIntResult(node->firstChild ? 1 : 0);
            } else {
                SetIntResult(0);
            }
            break;

        case m_childNodes:
            CheckArgs(2,2,2,"");
            resultPtr = Tcl_GetObjResult(interp);
            if (node->nodeType == ELEMENT_NODE) {
                child = node->firstChild;
                while (child != NULL) {
                    namePtr = tcldom_returnNodeObj(interp, child);

                    result  = Tcl_ListObjAppendElement(interp, resultPtr,
                                                       namePtr);
                    if (result != TCL_OK) {
                        Tcl_DecrRefCount(namePtr);
                        return result;
                    }
                    child = child->nextSibling;
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
        case m_getElementById:
            CheckArgs(3,3,2,"id");
            if (node->ownerDocument->ids) {
                str = Tcl_GetString(objv[2]);
                h = Tcl_FindHashEntry(node->ownerDocument->ids, str);
                if (h) {
                    domNode *node = Tcl_GetHashValue(h);
                    return tcldom_returnNodeObj(interp, node, 0, NULL);
                }
            }
            SetResult("");
            return TCL_OK;

        case m_nodeName:
            CheckArgs(2,2,2,"");







|







4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
        case m_getElementById:
            CheckArgs(3,3,2,"id");
            if (node->ownerDocument->ids) {
                str = Tcl_GetString(objv[2]);
                h = Tcl_FindHashEntry(node->ownerDocument->ids, str);
                if (h) {
                    domNode *node = Tcl_GetHashValue(h);
                    return tcldom_setInterpAndReturnVar(interp, node, 0, NULL);
                }
            }
            SetResult("");
            return TCL_OK;

        case m_nodeName:
            CheckArgs(2,2,2,"");
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
                    node->nodeFlags &= (~DISABLE_OUTPUT_ESCAPING);
                }
            }
            break;

        case m_precedes:
            CheckArgs(3,3,2, "node");
            nodeName = Tcl_GetString(objv[2]);
            refNode = tcldom_getNodeFromName(interp, nodeName, &errMsg);
            if (refNode == NULL) {
                SetResult(errMsg);
                return TCL_ERROR;
            }
            if (node->ownerDocument != refNode->ownerDocument) {
                SetResult("Cannot compare the relative order of nodes "
                          "out of different documents.");
                return TCL_ERROR;
            }







<
|

<







4668
4669
4670
4671
4672
4673
4674

4675
4676

4677
4678
4679
4680
4681
4682
4683
                    node->nodeFlags &= (~DISABLE_OUTPUT_ESCAPING);
                }
            }
            break;

        case m_precedes:
            CheckArgs(3,3,2, "node");

            refNode = tcldom_getNodeFromObj(interp, objv[2]);
            if (refNode == NULL) {

                return TCL_ERROR;
            }
            if (node->ownerDocument != refNode->ownerDocument) {
                SetResult("Cannot compare the relative order of nodes "
                          "out of different documents.");
                return TCL_ERROR;
            }
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
                                     node->ownerDocument, LOCK_WRITE);
        case m_readlock:
            CheckArgs(3,3,2,"script");
            return tcldom_EvalLocked(interp, (Tcl_Obj**)objv, 
                                     node->ownerDocument, LOCK_READ);
        )
    }
    return TCL_OK;
}


/*----------------------------------------------------------------------------
|   tcldom_DocObjCmd
|
\---------------------------------------------------------------------------*/
int tcldom_DocObjCmd (







|
|







4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
                                     node->ownerDocument, LOCK_WRITE);
        case m_readlock:
            CheckArgs(3,3,2,"script");
            return tcldom_EvalLocked(interp, (Tcl_Obj**)objv, 
                                     node->ownerDocument, LOCK_READ);
        )
    }
    return TCL_OK;}



/*----------------------------------------------------------------------------
|   tcldom_DocObjCmd
|
\---------------------------------------------------------------------------*/
int tcldom_DocObjCmd (
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
    |
    \---------------------------------------------------------------------*/

    switch ((enum docMethod) methodIndex ) {

        case m_documentElement:
            CheckArgs(2,3,2,"");
            return tcldom_returnNodeObj(interp, doc->documentElement,
                                        (objc == 3), 
                                        (objc == 3) ? objv[2] : NULL);
        case m_getElementsByTagName:
            CheckArgs(3,3,2,"elementName");
            return tcldom_getElementsByTagName(interp, Tcl_GetString(objv[2]),
                                               doc->documentElement, -1, NULL);
        case m_getElementsByTagNameNS:







|







4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
    |
    \---------------------------------------------------------------------*/

    switch ((enum docMethod) methodIndex ) {

        case m_documentElement:
            CheckArgs(2,3,2,"");
            return tcldom_setInterpAndReturnVar(interp, doc->documentElement,
                                        (objc == 3), 
                                        (objc == 3) ? objv[2] : NULL);
        case m_getElementsByTagName:
            CheckArgs(3,3,2,"elementName");
            return tcldom_getElementsByTagName(interp, Tcl_GetString(objv[2]),
                                               doc->documentElement, -1, NULL);
        case m_getElementsByTagNameNS:
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
                                               doc->documentElement, nsIndex,
                                               uri);
        case m_createElement:
            CheckArgs(3,4,2,"elementName ?newObjVar?");
            tag = Tcl_GetString(objv[2]);
            CheckName (interp, tag, "tag", 0);
            n = domNewElementNode(doc, tag, ELEMENT_NODE);
            return tcldom_returnNodeObj(interp, n, (objc == 4),
                                        (objc == 4) ? objv[3] : NULL);

        case m_createElementNS:
            CheckArgs(4,5,2,"elementName uri ?newObjVar?");
            uri = Tcl_GetString(objv[2]);
            tag = Tcl_GetString(objv[3]);
            CheckName (interp, tag, "full qualified tag", 1);
            n = domNewElementNodeNS(doc, tag, uri, ELEMENT_NODE);
            return tcldom_returnNodeObj(interp, n, (objc == 5),
                                        (objc == 5) ? objv[4] : NULL);

        case m_createTextNode:
            CheckArgs(3,4,2,"data ?newObjVar?");
            data = Tcl_GetStringFromObj(objv[2], &data_length);
            CheckText (interp, data, "text");
            n = (domNode*)domNewTextNode(doc, data, data_length, TEXT_NODE);
            return tcldom_returnNodeObj(interp, n, (objc == 4),
                                        (objc == 4) ? objv[3] : NULL);

        case m_createCDATASection:
            CheckArgs(3,4,2,"data ?newObjVar?");
            data = Tcl_GetStringFromObj(objv[2], &data_length);
            CheckCDATA (interp, data);
            n = (domNode*)domNewTextNode(doc, data, data_length, 
                                         CDATA_SECTION_NODE);
            return tcldom_returnNodeObj(interp, n, (objc == 4),
                                        (objc == 4) ? objv[3] : NULL);

        case m_createComment:
            CheckArgs(3,4,2,"data ?newObjVar?");
            data = Tcl_GetStringFromObj(objv[2], &data_length);
            CheckComment(interp, data);
            n = (domNode*)domNewTextNode(doc, data, data_length, COMMENT_NODE);
            return tcldom_returnNodeObj(interp, n, (objc == 4),
                                        (objc == 4) ? objv[3] : NULL);

        case m_createProcessingInstruction:
            CheckArgs(4,5,2,"target data ?newObjVar?");
            target = Tcl_GetStringFromObj(objv[2], &target_length);
            CheckPIName (interp, target);
            data   = Tcl_GetStringFromObj(objv[3], &data_length);
            CheckPIValue (interp, data);
            n = (domNode*)domNewProcessingInstructionNode(doc, target, 
                                                          target_length, data, 
                                                          data_length);
            return tcldom_returnNodeObj(interp, n, (objc == 5),
                                        (objc == 5) ? objv[4] : NULL);

        case m_delete:
            CheckArgs(2,2,2,"");
            if (clientData != NULL) {
                Tcl_DeleteCommand(interp, Tcl_GetString (objv[0]));
            } else {







|








|







|








|







|











|







4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
                                               doc->documentElement, nsIndex,
                                               uri);
        case m_createElement:
            CheckArgs(3,4,2,"elementName ?newObjVar?");
            tag = Tcl_GetString(objv[2]);
            CheckName (interp, tag, "tag", 0);
            n = domNewElementNode(doc, tag, ELEMENT_NODE);
            return tcldom_setInterpAndReturnVar(interp, n, (objc == 4),
                                        (objc == 4) ? objv[3] : NULL);

        case m_createElementNS:
            CheckArgs(4,5,2,"elementName uri ?newObjVar?");
            uri = Tcl_GetString(objv[2]);
            tag = Tcl_GetString(objv[3]);
            CheckName (interp, tag, "full qualified tag", 1);
            n = domNewElementNodeNS(doc, tag, uri, ELEMENT_NODE);
            return tcldom_setInterpAndReturnVar(interp, n, (objc == 5),
                                        (objc == 5) ? objv[4] : NULL);

        case m_createTextNode:
            CheckArgs(3,4,2,"data ?newObjVar?");
            data = Tcl_GetStringFromObj(objv[2], &data_length);
            CheckText (interp, data, "text");
            n = (domNode*)domNewTextNode(doc, data, data_length, TEXT_NODE);
            return tcldom_setInterpAndReturnVar(interp, n, (objc == 4),
                                        (objc == 4) ? objv[3] : NULL);

        case m_createCDATASection:
            CheckArgs(3,4,2,"data ?newObjVar?");
            data = Tcl_GetStringFromObj(objv[2], &data_length);
            CheckCDATA (interp, data);
            n = (domNode*)domNewTextNode(doc, data, data_length, 
                                         CDATA_SECTION_NODE);
            return tcldom_setInterpAndReturnVar(interp, n, (objc == 4),
                                        (objc == 4) ? objv[3] : NULL);

        case m_createComment:
            CheckArgs(3,4,2,"data ?newObjVar?");
            data = Tcl_GetStringFromObj(objv[2], &data_length);
            CheckComment(interp, data);
            n = (domNode*)domNewTextNode(doc, data, data_length, COMMENT_NODE);
            return tcldom_setInterpAndReturnVar(interp, n, (objc == 4),
                                        (objc == 4) ? objv[3] : NULL);

        case m_createProcessingInstruction:
            CheckArgs(4,5,2,"target data ?newObjVar?");
            target = Tcl_GetStringFromObj(objv[2], &target_length);
            CheckPIName (interp, target);
            data   = Tcl_GetStringFromObj(objv[3], &data_length);
            CheckPIValue (interp, data);
            n = (domNode*)domNewProcessingInstructionNode(doc, target, 
                                                          target_length, data, 
                                                          data_length);
            return tcldom_setInterpAndReturnVar(interp, n, (objc == 5),
                                        (objc == 5) ? objv[4] : NULL);

        case m_delete:
            CheckArgs(2,2,2,"");
            if (clientData != NULL) {
                Tcl_DeleteCommand(interp, Tcl_GetString (objv[0]));
            } else {

Added tests/dom.bench.



























































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
169
170
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
202
203
204
205
# -*- tcl -*-
# Tcl Benchmark File
#
# This file contains a number of benchmarks for the dom methods.
# This allow developers to monitor/gauge/track package performance.
#
# (c) 2013 Rolf Ade <rolf@pointsman.de>


# ### ### ### ######### ######### ######### ###########################
## Setting up the environment ...

package require tdom 

# ### ### ### ######### ######### ######### ###########################
## Benchmarks.

dom createNodeCmd elementNode e1

foreach nrOf {1 10 100 1000} {

    bench -desc "getElementsByTagName: $nrOf returned nodes" -pre {
        dom createDocument root doc
        $doc documentElement root
        $root appendFromScript {
            for {set x 0} {$x < $nrOf} {incr x} {
                e1
            }
        }
    } -body {
        $doc getElementsByTagName e1
    } -post {
        $doc delete
    }

}

foreach nrOf {1 10 100 1000} {

    bench -desc "getElementsByTagName: $nrOf returned node tokens" -pre {
        dom createDocument root doc
        $doc documentElement root
        $root appendFromScript {
            for {set x 0} {$x < $nrOf} {incr x} {
                e1
            }
        }
        dom setObjectCommands token
    } -body {
        $doc getElementsByTagName e1
    } -post {
        dom setObjectCommands automatic
        $doc delete
    }

}

proc cloneImitated {source target} {
    foreach att [$source attributes] {
        $target setAttribute $att [$source @$att]
    }
    set targetDoc [$target ownerDocument]
    foreach child [$source childNodes] {
        switch [$child nodeType] {
            "ELEMENT_NODE" {
                set targetChild [$targetDoc createElement [$child nodeName]]
            }
            "TEXT_NODE" {
                set targetChild [$targetDoc createTextNode [$child nodeValue]]
            }
            "CDATA_SECTION_NODE" {
                set targetChild [$targetDoc createCDATASection \
                                     [$child nodeValue]]
            }
            "PROCESSING_INSTRUCTION_NODE" {
                set targetChild [$targetDoc createProcessingInstruction \
                                     [$child nodeName] [$child nodeValue]]
            }
            "COMMENT_NODE" {
                set targetChild [$targetDoc createComment [$child nodeValue]]
            }
            default {
                error "Unexpected node type [$child nodeType]"
            }
        }
        $target appendChild $targetChild
        cloneImitated $child $targetChild
    }
}

proc cloneImitated2 {source target} {
    foreach att [$source attributes] {
        $target setAttribute $att [$source @$att]
    }
    set targetDoc [$target ownerDocument]
    foreach child [$source childNodes] {
        switch [$child nodeType] {
            "ELEMENT_NODE" {
                $targetDoc createElement [$child nodeName] targetChild
            }
            "TEXT_NODE" {
                $targetDoc createTextNode [$child nodeValue] targetChild
            }
            "CDATA_SECTION_NODE" {
                $targetDoc createCDATASection [$child nodeValue] targetChild
            }
            "PROCESSING_INSTRUCTION_NODE" {
                $targetDoc createProcessingInstruction [$child nodeName] \
                    targetChild
            }
            "COMMENT_NODE" {
                $targetDoc createComment [$child nodeValue] targetChild
            }
            default {
                error "Unexpected node type [$child nodeType]"
            }
        }
        $target appendChild $targetChild
        cloneImitated2 $child $targetChild
    }
}

proc cloneImitatedToken {source target} {
    foreach att [domNode $source attributes] {
        domNode $target setAttribute $att [domNode $source @$att]
    }
    set targetDoc [domNode $target ownerDocument]
    foreach child [domNode $source childNodes] {
        switch [domNode $child nodeType] {
            "ELEMENT_NODE" {
                set targetChild [$targetDoc createElement \
                                     [domNode $child nodeName]]
            }
            "TEXT_NODE" {
                set targetChild [$targetDoc createTextNode \
                                     [domNode $child nodeValue]]
            }
            "CDATA_SECTION_NODE" {
                set targetChild [$targetDoc createCDATASection \
                                     [domNode $child nodeValue]]
            }
            "PROCESSING_INSTRUCTION_NODE" {
                set targetChild [$targetDoc createProcessingInstruction \
                                     [domNode $child nodeName] \
                                     [domNode $child nodeValue]]
            }
            "COMMENT_NODE" {
                set targetChild [$targetDoc createComment \
                                     [domNode $child nodeValue]]
            }
            default {
                error "Unexpected node type [domNode $child nodeType]"
            }
        }
        domNode $target appendChild $targetChild
        cloneImitatedToken $child $targetChild
    }
}

bench -desc "clone dom tree without clone method - cmds" -pre {
    set fd [open [file join [file dir [info script]] ../tests/data/mondial-europe.xml]]
    fconfigure $fd -encoding utf-8
    set doc [dom parse -channel $fd]
    close $fd
    set root [$doc documentElement]
    set clone [dom createDocument [$root nodeName]]
    set cloneRoot [$clone documentElement]
} -iters 5 -body {
    cloneImitated $root $cloneRoot
} -post {
    $doc delete
    $clone delete
}

bench -desc "clone dom tree without clone method - cmds 2" -pre {
    set fd [open [file join [file dir [info script]] ../tests/data/mondial-europe.xml]]
    fconfigure $fd -encoding utf-8
    set doc [dom parse -channel $fd]
    close $fd
    set root [$doc documentElement]
    set clone [dom createDocument [$root nodeName]]
    set cloneRoot [$clone documentElement]
} -iters 5 -body {
    cloneImitated2 $root $cloneRoot
} -post {
    $doc delete
    $clone delete
}

bench -desc "clone dom tree without clone method - token" -pre {
    set fd [open [file join [file dir [info script]] ../tests/data/mondial-europe.xml]]
    fconfigure $fd -encoding utf-8
    set doc [dom parse -channel $fd]
    close $fd
    set root [$doc documentElement]
    set clone [dom createDocument [$root nodeName]]
    set cloneRoot [$clone documentElement]
    dom setObjectCommands token
} -iters 5 -body {
    cloneImitatedToken $root $cloneRoot
} -post {
    $doc delete
    $clone delete
    dom setObjectCommands automatic
}

Changes to tests/domNode.bench.

202
203
204
205
206
207
208






































































209
210
211
212
213
214
215
    } -body {
        $doc selectNodes -cache 1 count(/root/e1)
    } -post {
        $doc delete
    }

}







































































dom parse <root/> doc
$doc documentElement root

bench -desc "Check for text-only element - xpath - empty"  -body {
    for {set x 0} {$x < 100} {incr x} {
        $doc selectNodes -cache 1 {count(node()) = 1 and node() = text()}







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







202
203
204
205
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
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
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
    } -body {
        $doc selectNodes -cache 1 count(/root/e1)
    } -post {
        $doc delete
    }

}

foreach nrOf {1 10 100 1000} {

    bench -desc "getElementsByTagName: $nrOf returned nodes" -pre {
        dom createDocument root doc
        $doc documentElement root
        $root appendFromScript {
            for {set x 0} {$x < $nrOf} {incr x} {
                e1
            }
        }
    } -body {
        $doc getElementsByTagName e1
    } -post {
        $doc delete
    }

}

foreach nrOf {1 10 100 1000} {

    bench -desc "getElementsByTagName: $nrOf returned node tokens" -pre {
        dom createDocument root doc
        $doc documentElement root
        $root appendFromScript {
            for {set x 0} {$x < $nrOf} {incr x} {
                e1
            }
        }
        dom setObjectCommands token
    } -body {
        $doc getElementsByTagName e1
    } -post {
        dom setObjectCommands automatic
        $doc delete
    }

}


bench -desc "firstChild node cmd" -pre {
    dom parse <root><e/></root> doc
    $doc documentElement root
} -body {
    $root firstChild
} -post {
    $doc delete
}

bench -desc "firstChild node token" -pre {
    dom parse <root><e/></root> doc
    $doc documentElement root
    dom setObjectCommands token
} -body {
    $root firstChild
} -post {
    $doc delete
    dom setObjectCommands automatic
}

bench -desc "firstChild node token from node token" -pre {
    dom parse <root><e/></root> doc
    dom setObjectCommands token
    $doc documentElement root
} -body {
    domNode $root firstChild
} -post {
    $doc delete
    dom setObjectCommands automatic
}

dom parse <root/> doc
$doc documentElement root

bench -desc "Check for text-only element - xpath - empty"  -body {
    for {set x 0} {$x < 100} {incr x} {
        $doc selectNodes -cache 1 {count(node()) = 1 and node() = text()}