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

Changes In Branch stackless_asXML Excluding Merge-Ins

This is equivalent to a diff from 2b327d36f3 to 3c35cc9b09

2021-01-22
01:05
Enhance the pull-parser command find-element - skip forward not only to a specific element but to the first out of a list of elements. Thanks go to Mark Janssen for idea and contribution. check-in: 77f3b8498b user: rolf tags: trunk
2021-01-18
15:52
Add support for multiple names in find-element check-in: 9a2bc3a9f7 user: mjanssen tags: find-multiple-elements
2021-01-06
22:34
If asXML -indent tab is used now comments and processing instructions are also indented with tabs. Leaf check-in: 3c35cc9b09 user: rolf tags: stackless_asXML
18:16
Better implementation of indentation with tabs or white space. check-in: a4dcb11f16 user: rolf tags: stackless_asXML
02:34
Merged from trunk. check-in: 226d987aaa user: rolf tags: stackless_asXML
2021-01-03
01:37
Merged from trunk. check-in: 57df626882 user: rolf tags: toschema
2020-12-31
01:18
Correct cleanup in case of failing conversion of a dom tree into an xslt command. check-in: 2b327d36f3 user: rolf tags: trunk
2020-12-28
01:38
Add compatibility to older gcc compiler. check-in: 4373add689 user: rolf tags: trunk

Changes to generic/dom.h.

100
101
102
103
104
105
106




107
108
109
110
111
112
113
 */
#if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION < 2)
# define Tcl_Panic panic
# define Tcl_GetString(a) Tcl_GetStringFromObj((a), NULL)
#endif

#define domPanic(msg) Tcl_Panic((msg));





/*
 * If compiled against threaded Tcl core, we must take
 * some extra care about process-wide globals and the
 * way we name Tcl object accessor commands.
 */
#ifndef TCL_THREADS







>
>
>
>







100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
 */
#if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION < 2)
# define Tcl_Panic panic
# define Tcl_GetString(a) Tcl_GetStringFromObj((a), NULL)
#endif

#define domPanic(msg) Tcl_Panic((msg));

#ifndef STATIC_STACK_SIZE
# define STATIC_STACK_SIZE 32
#endif

/*
 * If compiled against threaded Tcl core, we must take
 * some extra care about process-wide globals and the
 * way we name Tcl object accessor commands.
 */
#ifndef TCL_THREADS

Changes to generic/tcldom.c.

392
393
394
395
396
397
398





399
400
401
402
403
404
405
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;







>
>
>
>
>







392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
const Tcl_ObjType tdomNodeType = {
    "tdom-node",
    NULL,
    NULL,
    UpdateStringOfTdomNode,
    SetTdomNodeFromAny
};

typedef struct {
    domNode *node;
    int      cdata;
} asXMLStack;

/*----------------------------------------------------------------------------
|   Prototypes for procedures defined later in this file:
|
\---------------------------------------------------------------------------*/
static Tcl_VarTraceProc  tcldom_docTrace;
static Tcl_CmdDeleteProc tcldom_docCmdDeleteProc;
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780


2781
2782
2783


2784
2785
2786
2787
2788
2789
2790
2791
    if (!onlyContents) {
        writeChars(htmlString, chan, "</", 2);
        writeChars(htmlString, chan, tag, -1);
        writeChars(htmlString, chan, ">",  1);
    }
}


/*----------------------------------------------------------------------------
|   tcldom_treeAsXML
|
\---------------------------------------------------------------------------*/
static
void tcldom_treeAsXML (
    Tcl_Obj    *xmlString,
    domNode    *node,
    int         indent,
    int         level,
    int         doIndent,
    Tcl_Channel chan,
    Tcl_Obj    *encString,
    int         cdataChild,
    int         outputFlags,
    int         indentAttrs
)
{
    domAttrNode   *attrs;


    domNode       *child;
    domDocument   *doc;
    int            first, hasElements, i;


    char           prefix[MAX_PREFIX_LEN], *start, *p;
    const char    *localName;
    Tcl_HashEntry *h;
    Tcl_DString    dStr;

    if (outputFlags & SERIALIZE_XML_DECLARATION) {
        outputFlags &= ~SERIALIZE_XML_DECLARATION;
        writeChars(xmlString, chan, "<?xml version=\"1.0\"", 19);







<









<
<


<





>
>
|

|
>
>
|







2759
2760
2761
2762
2763
2764
2765

2766
2767
2768
2769
2770
2771
2772
2773
2774


2775
2776

2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
    if (!onlyContents) {
        writeChars(htmlString, chan, "</", 2);
        writeChars(htmlString, chan, tag, -1);
        writeChars(htmlString, chan, ">",  1);
    }
}


/*----------------------------------------------------------------------------
|   tcldom_treeAsXML
|
\---------------------------------------------------------------------------*/
static
void tcldom_treeAsXML (
    Tcl_Obj    *xmlString,
    domNode    *node,
    int         indent,


    Tcl_Channel chan,
    Tcl_Obj    *encString,

    int         outputFlags,
    int         indentAttrs
)
{
    domAttrNode   *attrs;
    asXMLStack     staticStack[STATIC_STACK_SIZE];
    asXMLStack    *dynStack = NULL;
    int            dynStackSize = 0;
    domDocument   *doc;
    int            isDoc = 0;
    int            level = 0, cdataChild = 0;
    int            i, indBufCount, attindBufCount;
    char           prefix[MAX_PREFIX_LEN], *start, *p, *indBuf, *attindBuf;
    const char    *localName;
    Tcl_HashEntry *h;
    Tcl_DString    dStr;

    if (outputFlags & SERIALIZE_XML_DECLARATION) {
        outputFlags &= ~SERIALIZE_XML_DECLARATION;
        writeChars(xmlString, chan, "<?xml version=\"1.0\"", 19);
2801
2802
2803
2804
2805
2806
2807

2808
2809
2810
2811
2812
2813
2814
            writeChars(xmlString, chan,
                       ((domDocument*) node)->doctype->encoding, -1);
            writeChars(xmlString, chan, "\"", 1);
        }
        writeChars(xmlString, chan, "?>\n", 3);
    }
    if (node->nodeType == DOCUMENT_NODE) {

        doc = (domDocument*) node;
        if (outputFlags & SERIALIZE_DOCTYPE_DECLARATION
            && doc->documentElement) {
            writeChars(xmlString, chan, "<!DOCTYPE ", 10);
            writeChars(xmlString, chan, doc->documentElement->nodeName, -1);
            if (   doc->doctype 
                && doc->doctype->systemId







>







2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
            writeChars(xmlString, chan,
                       ((domDocument*) node)->doctype->encoding, -1);
            writeChars(xmlString, chan, "\"", 1);
        }
        writeChars(xmlString, chan, "?>\n", 3);
    }
    if (node->nodeType == DOCUMENT_NODE) {
        isDoc = 1;
        doc = (domDocument*) node;
        if (outputFlags & SERIALIZE_DOCTYPE_DECLARATION
            && doc->documentElement) {
            writeChars(xmlString, chan, "<!DOCTYPE ", 10);
            writeChars(xmlString, chan, doc->documentElement->nodeName, -1);
            if (   doc->doctype 
                && doc->doctype->systemId
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842



2843


2844






2845

2846

2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910




2911
2912

2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924






2925





2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962

2963





2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987

2988
2989
2990

2991
2992
2993
2994
2995







2996
2997
2998
2999
3000
3001


3002
3003
3004
3005


3006

3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018

3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034









3035
3036
3037
3038
3039

3040
3041

















3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053






















3054
3055
3056
3057
3058
3059
3060
                    writeChars(xmlString, chan, doc->doctype->internalSubset,
                               -1);
                    writeChars(xmlString, chan, "]", 1);
                }
            }
            writeChars(xmlString, chan, ">\n", 2);
        }
        child = doc->rootNode->firstChild;
        while (child) {
            tcldom_treeAsXML(xmlString, child, indent, level, doIndent, chan,
                             NULL, 0, outputFlags, indentAttrs);
            child = child->nextSibling;
        }



        return;


    }








    if (node->nodeType == TEXT_NODE) {

        if (cdataChild) {
            writeChars(xmlString, chan, "<![CDATA[", 9);
            i = 0;
            start = p = ((domTextNode*)node)->nodeValue;
            while (i < ((domTextNode*)node)->valueLength) {
                if (*p == ']') {
                    p++; i++;;
                    if (i >= ((domTextNode*)node)->valueLength) break;
                    if (*p == ']') {
                        p++; i++;;
                        if (i >= ((domTextNode*)node)->valueLength) break;
                        if (*p == '>') {
                            writeChars(xmlString, chan, start, p-start);
                            writeChars(xmlString, chan, "]]><![CDATA[>", 13);
                            start = p+1;
                        }
                    }
                }
                p++; i++;;
            }
            writeChars(xmlString, chan, start, p-start);
            writeChars(xmlString, chan, "]]>", 3);
        } else {
            if (node->nodeFlags & DISABLE_OUTPUT_ESCAPING) {
                writeChars(xmlString, chan, ((domTextNode*)node)->nodeValue,
                           ((domTextNode*)node)->valueLength);
            } else {
                tcldom_AppendEscaped(xmlString, chan,
                                     ((domTextNode*)node)->nodeValue,
                                     ((domTextNode*)node)->valueLength,
                                     outputFlags);
            }
        }
        return;
    }

    if (node->nodeType == CDATA_SECTION_NODE) {
        writeChars(xmlString, chan, "<![CDATA[", 9);
        writeChars(xmlString, chan, ((domTextNode*)node)->nodeValue,
                                    ((domTextNode*)node)->valueLength);
        writeChars(xmlString, chan, "]]>", 3);
        return;
    }

    if ((indent != -1) && doIndent) {
        if (outputFlags & SERIALIZE_INDENT_WITH_TAB) {
            for(i=0; i<level; i++) {
                writeChars(xmlString, chan, "\t", 1);
            }
        } else {
            for(i=0; i<level; i++) {
                writeChars(xmlString, chan, "        ", indent);
            }
        }
    }

    if (node->nodeType == COMMENT_NODE) {
        writeChars(xmlString, chan, "<!--", 4);
        writeChars(xmlString, chan, ((domTextNode*)node)->nodeValue,
                                    ((domTextNode*)node)->valueLength);
        writeChars(xmlString, chan, "-->", 3);
        if (indent != -1) writeChars (xmlString, chan, "\n", 1);
        return;
    }





    if (node->nodeType == PROCESSING_INSTRUCTION_NODE) {

        writeChars(xmlString, chan, "<?", 2);
        writeChars(xmlString, chan, 
                    ((domProcessingInstructionNode*)node)->targetValue,
                    ((domProcessingInstructionNode*)node)->targetLength);
        writeChars(xmlString, chan, " ", 1);
        writeChars(xmlString, chan, 
                   ((domProcessingInstructionNode*)node)->dataValue,
                   ((domProcessingInstructionNode*)node)->dataLength);
        writeChars(xmlString, chan, "?>", 2);
        if (indent != -1) writeChars (xmlString, chan, "\n", 1);
        return;
    }












    writeChars(xmlString, chan, "<", 1);
    writeChars(xmlString, chan, node->nodeName, -1);

    attrs = node->firstAttr;
    while (attrs) {
        if (indentAttrs > -1) {
            writeChars(xmlString, chan, "\n", 1);
            if ((indent != -1) && doIndent) {
                if (outputFlags & SERIALIZE_INDENT_WITH_TAB) {
                    for(i=0; i<level; i++) {
                        writeChars(xmlString, chan, "\t", 1);
                    }
                } else {
                    for(i=0; i<level; i++) {
                        writeChars(xmlString, chan, "        ", indent);
                    }
                }
                if (outputFlags & SERIALIZE_INDENT_ATTR_WITH_TAB) {
                    writeChars(xmlString, chan, "\t", 1);
                } else {
                    writeChars(xmlString, chan, "        ", indentAttrs);
                }
            }
        } else {
            writeChars(xmlString, chan, " ", 1);
        }
        writeChars(xmlString, chan, attrs->nodeName, -1);
        writeChars(xmlString, chan, "=\"", 2);
        tcldom_AppendEscaped(xmlString, chan, attrs->nodeValue, 
                             attrs->valueLength,
                             outputFlags | SERIALIZE_FOR_ATTR);
        writeChars(xmlString, chan, "\"", 1);
        attrs = attrs->nextSibling;
    }

    hasElements = 0;
    first       = 1;

    doIndent    = 1;






    if (node->nodeType == ELEMENT_NODE) {
        cdataChild = 0;
        if (node->ownerDocument->doctype
            && node->ownerDocument->doctype->cdataSectionElements) {
            if (node->namespace) {
                Tcl_DStringInit (&dStr);
                Tcl_DStringAppend (&dStr, domNamespaceURI(node), -1);
                Tcl_DStringAppend (&dStr, ":", 1);
                domSplitQName (node->nodeName, prefix, &localName);
                Tcl_DStringAppend (&dStr, localName, -1);
                h = Tcl_FindHashEntry (
                    node->ownerDocument->doctype->cdataSectionElements,
                    Tcl_DStringValue (&dStr));
                Tcl_DStringFree (&dStr);
            } else {
                h = Tcl_FindHashEntry (
                    node->ownerDocument->doctype->cdataSectionElements,
                    node->nodeName);
            }
            if (h) {
                cdataChild = 1;
            }
        }

        child = node->firstChild;
        while (child != NULL) {


            if (  (child->nodeType == ELEMENT_NODE)
                ||(child->nodeType == PROCESSING_INSTRUCTION_NODE)
                ||(child->nodeType == COMMENT_NODE) )
            {
                hasElements = 1;







            }
            if (first) {
                writeChars(xmlString, chan, ">", 1);
                if ((indent != -1) && hasElements) {
                    writeChars(xmlString, chan, "\n", 1);
                }


            }
            first = 0;
            tcldom_treeAsXML(xmlString, child, indent, level+1, doIndent,
                             chan, NULL, cdataChild, outputFlags, indentAttrs);


            doIndent = 0;

            if (  (child->nodeType == ELEMENT_NODE)
                ||(child->nodeType == PROCESSING_INSTRUCTION_NODE)
                ||(child->nodeType == COMMENT_NODE) )
            {
               doIndent = 1;
            }
            child = child->nextSibling;
        }
    }

    if (first) {
        if (indent != -1) {

            if (outputFlags & SERIALIZE_NO_EMPTY_ELEMENT_TAG) {
                writeChars (xmlString, chan, "></", 3);
                writeChars(xmlString, chan, node->nodeName, -1);
                writeChars(xmlString, chan, ">\n", 2);
            } else {
                writeChars(xmlString, chan, "/>\n", 3);
            }
        } else {
            if (outputFlags & SERIALIZE_NO_EMPTY_ELEMENT_TAG) {
                writeChars (xmlString, chan, "></", 3);
                writeChars(xmlString, chan, node->nodeName, -1);
                writeChars(xmlString, chan, ">", 1);
            } else {
                writeChars(xmlString, chan, "/>",   2);
            }
        }









    } else {
        if ((indent != -1) && hasElements) {
            if (outputFlags & SERIALIZE_INDENT_WITH_TAB) {
                for(i=0; i<level; i++) {
                    writeChars(xmlString, chan, "\t", 1);

                }
            } else {

















                for(i=0; i<level; i++) {
                    writeChars(xmlString, chan, "        ", indent);
                }
            }
        }
        writeChars (xmlString, chan, "</", 2);
        writeChars(xmlString, chan, node->nodeName, -1);
        if (indent != -1) {
            writeChars(xmlString, chan, ">\n", 2);
        } else {
            writeChars(xmlString, chan, ">",   1);
        }






















    }
}

/*----------------------------------------------------------------------------
|   tcldom_AppendEscapedJSON
|
\---------------------------------------------------------------------------*/







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

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

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

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







2836
2837
2838
2839
2840
2841
2842
2843




2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896

2897
2898
2899
2900
2901
2902
2903
2904
2905

2906
2907
2908



2909




2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921

2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954

2955
2956
2957






2958



2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971

2972
2973
2974
2975
2976
2977
2978
2979
2980

2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008



3009
3010
3011
3012
3013
3014
3015
3016
3017




3018
3019
3020
3021

3022
3023
3024
3025
3026
3027
3028
3029
3030






3031


3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058




3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082

3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
                    writeChars(xmlString, chan, doc->doctype->internalSubset,
                               -1);
                    writeChars(xmlString, chan, "]", 1);
                }
            }
            writeChars(xmlString, chan, ">\n", 2);
        }
        node = doc->rootNode->firstChild;




    }
    if (outputFlags & SERIALIZE_INDENT_WITH_TAB) {
        indBuf = "\t";
        indBufCount = 1;
    } else {
        indBuf = "        ";
        indBufCount = indent;
    }
    if (outputFlags & SERIALIZE_INDENT_ATTR_WITH_TAB) {
        attindBuf = "\t";
        attindBufCount = 1;
    } else {
        attindBuf = "        ";
        attindBufCount = indentAttrs;
    }
    while (node) {
        switch (node->nodeType) {
        case TEXT_NODE:
            if (cdataChild) {
                writeChars(xmlString, chan, "<![CDATA[", 9);
                i = 0;
                start = p = ((domTextNode*)node)->nodeValue;
                while (i < ((domTextNode*)node)->valueLength) {
                    if (*p == ']') {
                        p++; i++;;
                        if (i >= ((domTextNode*)node)->valueLength) break;
                        if (*p == ']') {
                            p++; i++;;
                            if (i >= ((domTextNode*)node)->valueLength) break;
                            if (*p == '>') {
                                writeChars(xmlString, chan, start, p-start);
                                writeChars(xmlString, chan, "]]><![CDATA[>", 13);
                                start = p+1;
                            }
                        }
                    }
                    p++; i++;;
                }
                writeChars(xmlString, chan, start, p-start);
                writeChars(xmlString, chan, "]]>", 3);
            } else {
                if (node->nodeFlags & DISABLE_OUTPUT_ESCAPING) {
                    writeChars(xmlString, chan, ((domTextNode*)node)->nodeValue,
                               ((domTextNode*)node)->valueLength);
                } else {
                    tcldom_AppendEscaped(xmlString, chan,
                                         ((domTextNode*)node)->nodeValue,
                                         ((domTextNode*)node)->valueLength,
                                         outputFlags);
                }
            }
            break;


        case CDATA_SECTION_NODE:
            writeChars(xmlString, chan, "<![CDATA[", 9);
            writeChars(xmlString, chan, ((domTextNode*)node)->nodeValue,
                       ((domTextNode*)node)->valueLength);
            writeChars(xmlString, chan, "]]>", 3);
            break;

        case COMMENT_NODE:
            if (indent != -1) {

                for(i=0; i<level; i++) {
                    writeChars(xmlString, chan, indBuf, indBufCount);
                }



            }




            writeChars(xmlString, chan, "<!--", 4);
            writeChars(xmlString, chan, ((domTextNode*)node)->nodeValue,
                       ((domTextNode*)node)->valueLength);
            writeChars(xmlString, chan, "-->", 3);
            if (indent != -1) writeChars (xmlString, chan, "\n", 1);
            break;
        
        case PROCESSING_INSTRUCTION_NODE:
            if (indent != -1) {
                for(i=0; i<level; i++) {
                    writeChars(xmlString, chan, indBuf, indBufCount);
                }

            }
            writeChars(xmlString, chan, "<?", 2);
            writeChars(xmlString, chan, 
                       ((domProcessingInstructionNode*)node)->targetValue,
                       ((domProcessingInstructionNode*)node)->targetLength);
            writeChars(xmlString, chan, " ", 1);
            writeChars(xmlString, chan, 
                       ((domProcessingInstructionNode*)node)->dataValue,
                       ((domProcessingInstructionNode*)node)->dataLength);
            writeChars(xmlString, chan, "?>", 2);
            if (indent != -1) writeChars (xmlString, chan, "\n", 1);
            break;

        case ELEMENT_NODE:
            if (indent != -1 &&
                (node->previousSibling == NULL ||
                 ((node->previousSibling->nodeType == ELEMENT_NODE) ||
                  (node->previousSibling->nodeType == PROCESSING_INSTRUCTION_NODE) ||
                  (node->previousSibling->nodeType == COMMENT_NODE)))
                )
            {
                for(i=0; i<level; i++) {
                    writeChars(xmlString, chan, indBuf, indBufCount);
                }
            }
            writeChars(xmlString, chan, "<", 1);
            writeChars(xmlString, chan, node->nodeName, -1);
            
            attrs = node->firstAttr;
            while (attrs) {
                if (indentAttrs > -1) {
                    writeChars(xmlString, chan, "\n", 1);
                    if (indent != -1) {

                        for(i=0; i<level; i++) {
                            writeChars(xmlString, chan, indBuf, indBufCount);
                        }






                        writeChars(xmlString, chan, attindBuf, attindBufCount);



                    }
                } else {
                    writeChars(xmlString, chan, " ", 1);
                }
                writeChars(xmlString, chan, attrs->nodeName, -1);
                writeChars(xmlString, chan, "=\"", 2);
                tcldom_AppendEscaped(xmlString, chan, attrs->nodeValue, 
                                     attrs->valueLength,
                                     outputFlags | SERIALIZE_FOR_ATTR);
                writeChars(xmlString, chan, "\"", 1);
                attrs = attrs->nextSibling;
            }


            if (node->firstChild) {
                writeChars(xmlString, chan, ">", 1);
                if (indent != -1
                    && (  (node->firstChild->nodeType == ELEMENT_NODE)
                        ||(node->firstChild->nodeType == PROCESSING_INSTRUCTION_NODE)
                        ||(node->firstChild->nodeType == COMMENT_NODE) )
                    ) {
                    writeChars(xmlString, chan, "\n", 1);
                }

                cdataChild = 0;
                if (node->ownerDocument->doctype
                    && node->ownerDocument->doctype->cdataSectionElements) {
                    if (node->namespace) {
                        Tcl_DStringInit (&dStr);
                        Tcl_DStringAppend (&dStr, domNamespaceURI(node), -1);
                        Tcl_DStringAppend (&dStr, ":", 1);
                        domSplitQName (node->nodeName, prefix, &localName);
                        Tcl_DStringAppend (&dStr, localName, -1);
                        h = Tcl_FindHashEntry (
                            node->ownerDocument->doctype->cdataSectionElements,
                            Tcl_DStringValue (&dStr));
                        Tcl_DStringFree (&dStr);
                    } else {
                        h = Tcl_FindHashEntry (
                            node->ownerDocument->doctype->cdataSectionElements,
                            node->nodeName);
                    }
                    if (h) {
                        cdataChild = 1;
                    }
                }
                if (level < STATIC_STACK_SIZE) {
                    staticStack[level].node = node;
                    staticStack[level].cdata = cdataChild;
                } else {
                    if (level >= STATIC_STACK_SIZE + dynStackSize) {
                        if (dynStackSize) {



                            dynStack = (asXMLStack *)
                                REALLOC (dynStack,
                                         sizeof(asXMLStack)*dynStackSize*2);
                            dynStackSize *= 2;
                        } else {
                            dynStack = (asXMLStack *)
                                MALLOC (sizeof(asXMLStack)*STATIC_STACK_SIZE);
                            dynStackSize = STATIC_STACK_SIZE;
                        }




                    }
                    dynStack[level-STATIC_STACK_SIZE].node = node;
                    dynStack[level-STATIC_STACK_SIZE].cdata = cdataChild;
                }

                level++;
                node = node->firstChild;
                continue;
            } else {
                if (indent != -1 &&
                    (node->nextSibling == NULL ||
                     ((node->nextSibling->nodeType == ELEMENT_NODE) ||
                      (node->nextSibling->nodeType == PROCESSING_INSTRUCTION_NODE) ||
                      (node->nextSibling->nodeType == COMMENT_NODE)))






                    )


                {
                    if (outputFlags & SERIALIZE_NO_EMPTY_ELEMENT_TAG) {
                        writeChars (xmlString, chan, "></", 3);
                        writeChars(xmlString, chan, node->nodeName, -1);
                        writeChars(xmlString, chan, ">\n", 2);
                    } else {
                        writeChars(xmlString, chan, "/>\n", 3);
                    }
                } else {
                    if (outputFlags & SERIALIZE_NO_EMPTY_ELEMENT_TAG) {
                        writeChars (xmlString, chan, "></", 3);
                        writeChars(xmlString, chan, node->nodeName, -1);
                        writeChars(xmlString, chan, ">", 1);
                    } else {
                        writeChars(xmlString, chan, "/>",   2);
                    }
                }
            }
        default:
            /* Does not happen */
            ;
        }
        
        if (level == 0) {
            if (isDoc) {
                node = node->nextSibling;
            } else {




                break;
            }
        } else {
            if (node->nextSibling) {
                node = node->nextSibling;
            } else {
                while (1) {
                    level--;
                    if (level < STATIC_STACK_SIZE) {
                        node = staticStack[level].node;
                        cdataChild = staticStack[level].cdata;
                    } else {
                        node = dynStack[level-STATIC_STACK_SIZE].node;
                        cdataChild = dynStack[level-STATIC_STACK_SIZE].cdata;
                    }
                    if (indent != -1 
                        && (   node->firstChild->nodeType == ELEMENT_NODE
                               || node->firstChild->nodeType == PROCESSING_INSTRUCTION_NODE
                               || node->firstChild->nodeType == COMMENT_NODE )
                        ) {
                        for(i=0; i<level; i++) {
                            writeChars(xmlString, chan, indBuf, indBufCount);
                        }
                    }

                    writeChars (xmlString, chan, "</", 2);
                    writeChars(xmlString, chan, node->nodeName, -1);
                    if (indent != -1) {
                        writeChars(xmlString, chan, ">\n", 2);
                    } else {
                        writeChars(xmlString, chan, ">",   1);
                    }
                    if (level > 0) {
                        if (node->nextSibling) {
                            cdataChild = staticStack[level-1].cdata;
                            node = node->nextSibling;
                            break;
                        } else {
                            continue;
                        }
                    } else {
                        if (isDoc) {
                            node = node->nextSibling;
                        } else {
                            node = NULL;
                        }
                        break;
                    }
                }
            }
        }
    }
    if (dynStackSize) {
        FREE (dynStack);
    }
}

/*----------------------------------------------------------------------------
|   tcldom_AppendEscapedJSON
|
\---------------------------------------------------------------------------*/
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
static int serializeAsXML (
    domNode    *node,
    Tcl_Interp *interp,
    int         objc,
    Tcl_Obj    *const objv[]
)
{
    char          *channelId, prefix[MAX_PREFIX_LEN];
    const char    *localName;
    int            indent, mode, bool;
    int            outputFlags = 0;
    int            optionIndex, cdataChild;
    Tcl_Obj       *resultPtr, *encString = NULL;
    Tcl_Channel    chan = (Tcl_Channel) NULL;
    Tcl_HashEntry *h;
    Tcl_DString    dStr;
    int            indentAttrs = -1;

    static const char *asXMLOptions[] = {
        "-indent", "-channel", "-escapeNonASCII", "-doctypeDeclaration",
        "-xmlDeclaration", "-encString", "-escapeAllQuot", "-indentAttrs",
        "-nogtescape", "-noEmptyElementTag",
        NULL







|
<


|


<
<







3548
3549
3550
3551
3552
3553
3554
3555

3556
3557
3558
3559
3560


3561
3562
3563
3564
3565
3566
3567
static int serializeAsXML (
    domNode    *node,
    Tcl_Interp *interp,
    int         objc,
    Tcl_Obj    *const objv[]
)
{
    char          *channelId;

    int            indent, mode, bool;
    int            outputFlags = 0;
    int            optionIndex;
    Tcl_Obj       *resultPtr, *encString = NULL;
    Tcl_Channel    chan = (Tcl_Channel) NULL;


    int            indentAttrs = -1;

    static const char *asXMLOptions[] = {
        "-indent", "-channel", "-escapeNonASCII", "-doctypeDeclaration",
        "-xmlDeclaration", "-encString", "-escapeAllQuot", "-indentAttrs",
        "-nogtescape", "-noEmptyElementTag",
        NULL
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
            break;
        }
    }
    if (indent > 8)  indent = 8;
    if (indent < -1) indent = -1;

    resultPtr = Tcl_NewStringObj("", 0);
    cdataChild = 0;
    if (node->nodeType == ELEMENT_NODE
        && node->ownerDocument->doctype 
        && node->ownerDocument->doctype->cdataSectionElements) {
        if (node->namespace) {
            Tcl_DStringInit (&dStr);
            Tcl_DStringAppend (&dStr, domNamespaceURI(node), -1);
            Tcl_DStringAppend (&dStr, ":", 1);
            domSplitQName (node->nodeName, prefix, &localName);
            Tcl_DStringAppend (&dStr, localName, -1);
            h = Tcl_FindHashEntry (
                node->ownerDocument->doctype->cdataSectionElements,
                Tcl_DStringValue (&dStr));
            Tcl_DStringFree (&dStr);
        } else {
            h = Tcl_FindHashEntry (
                node->ownerDocument->doctype->cdataSectionElements,
                node->nodeName);
        }
        if (h) {
            cdataChild = 1;
        }
    }
    tcldom_treeAsXML(resultPtr, node, indent, 0, 1, chan, encString,
                     cdataChild, outputFlags, indentAttrs);
    Tcl_SetObjResult(interp, resultPtr);
    if (encString) {
        Tcl_DecrRefCount(encString);
    }
    return TCL_OK;
cleanup:
    if (encString) {







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







3725
3726
3727
3728
3729
3730
3731























3732
3733
3734
3735
3736
3737
3738
3739
3740
            break;
        }
    }
    if (indent > 8)  indent = 8;
    if (indent < -1) indent = -1;

    resultPtr = Tcl_NewStringObj("", 0);























    tcldom_treeAsXML(resultPtr, node, indent, chan, encString,
                     outputFlags, indentAttrs);
    Tcl_SetObjResult(interp, resultPtr);
    if (encString) {
        Tcl_DecrRefCount(encString);
    }
    return TCL_OK;
cleanup:
    if (encString) {

Changes to tests/domDoc.test.

367
368
369
370
371
372
373














374
375
376
377
378
379
380
    $doc delete
    set result
} {<html
><body
><p
>boo</p></body></html>}















set doc [dom parse <root/>]

test domDoc-2.1 {publicId - no publicId there} {
    $doc publicId
} {}

test domDoc-2.2 {systemId - no systemId there} {







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







367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
    $doc delete
    set result
} {<html
><body
><p
>boo</p></body></html>}

test domDoc-1.39 {asXML -indent tabs w/ comment} {
    set doc [dom parse {<doc><a><!-- comment one --><b/><!-- comment two --></a><!-- comment three --></doc>}]
    set result [$doc asXML -indent tabs]
    $doc delete
    set result
} "<doc>\n\t<a\>\n\t\t<!-- comment one -->\n\t\t<b/>\n\t\t<!-- comment two -->\n\t</a>\n\t<!-- comment three -->\n</doc>\n"

test domDoc-1.40 {asXML -indent tabs w/ processing-instruction} {
    set doc [dom parse {<doc><a><?p 1?><b/><?p 2?></a><?p 3?></doc>}]
    set result [$doc asXML -indent tabs]
    $doc delete
    set result
} "<doc>\n\t<a\>\n\t\t<?p 1?>\n\t\t<b/>\n\t\t<?p 2?>\n\t</a>\n\t<?p 3?>\n</doc>\n"

set doc [dom parse <root/>]

test domDoc-2.1 {publicId - no publicId there} {
    $doc publicId
} {}

test domDoc-2.2 {systemId - no systemId there} {