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    100    */
   101    101   #if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION < 2)
   102    102   # define Tcl_Panic panic
   103    103   # define Tcl_GetString(a) Tcl_GetStringFromObj((a), NULL)
   104    104   #endif
   105    105   
   106    106   #define domPanic(msg) Tcl_Panic((msg));
          107  +
          108  +#ifndef STATIC_STACK_SIZE
          109  +# define STATIC_STACK_SIZE 32
          110  +#endif
   107    111   
   108    112   /*
   109    113    * If compiled against threaded Tcl core, we must take
   110    114    * some extra care about process-wide globals and the
   111    115    * way we name Tcl object accessor commands.
   112    116    */
   113    117   #ifndef TCL_THREADS

Changes to generic/tcldom.c.

   392    392   const Tcl_ObjType tdomNodeType = {
   393    393       "tdom-node",
   394    394       NULL,
   395    395       NULL,
   396    396       UpdateStringOfTdomNode,
   397    397       SetTdomNodeFromAny
   398    398   };
          399  +
          400  +typedef struct {
          401  +    domNode *node;
          402  +    int      cdata;
          403  +} asXMLStack;
   399    404   
   400    405   /*----------------------------------------------------------------------------
   401    406   |   Prototypes for procedures defined later in this file:
   402    407   |
   403    408   \---------------------------------------------------------------------------*/
   404    409   static Tcl_VarTraceProc  tcldom_docTrace;
   405    410   static Tcl_CmdDeleteProc tcldom_docCmdDeleteProc;
................................................................................
  2754   2759       if (!onlyContents) {
  2755   2760           writeChars(htmlString, chan, "</", 2);
  2756   2761           writeChars(htmlString, chan, tag, -1);
  2757   2762           writeChars(htmlString, chan, ">",  1);
  2758   2763       }
  2759   2764   }
  2760   2765   
  2761         -
  2762   2766   /*----------------------------------------------------------------------------
  2763   2767   |   tcldom_treeAsXML
  2764   2768   |
  2765   2769   \---------------------------------------------------------------------------*/
  2766   2770   static
  2767   2771   void tcldom_treeAsXML (
  2768   2772       Tcl_Obj    *xmlString,
  2769   2773       domNode    *node,
  2770   2774       int         indent,
  2771         -    int         level,
  2772         -    int         doIndent,
  2773   2775       Tcl_Channel chan,
  2774   2776       Tcl_Obj    *encString,
  2775         -    int         cdataChild,
  2776   2777       int         outputFlags,
  2777   2778       int         indentAttrs
  2778   2779   )
  2779   2780   {
  2780   2781       domAttrNode   *attrs;
  2781         -    domNode       *child;
         2782  +    asXMLStack     staticStack[STATIC_STACK_SIZE];
         2783  +    asXMLStack    *dynStack = NULL;
         2784  +    int            dynStackSize = 0;
  2782   2785       domDocument   *doc;
  2783         -    int            first, hasElements, i;
  2784         -    char           prefix[MAX_PREFIX_LEN], *start, *p;
         2786  +    int            isDoc = 0;
         2787  +    int            level = 0, cdataChild = 0;
         2788  +    int            i, indBufCount, attindBufCount;
         2789  +    char           prefix[MAX_PREFIX_LEN], *start, *p, *indBuf, *attindBuf;
  2785   2790       const char    *localName;
  2786   2791       Tcl_HashEntry *h;
  2787   2792       Tcl_DString    dStr;
  2788   2793   
  2789   2794       if (outputFlags & SERIALIZE_XML_DECLARATION) {
  2790   2795           outputFlags &= ~SERIALIZE_XML_DECLARATION;
  2791   2796           writeChars(xmlString, chan, "<?xml version=\"1.0\"", 19);
................................................................................
  2801   2806               writeChars(xmlString, chan,
  2802   2807                          ((domDocument*) node)->doctype->encoding, -1);
  2803   2808               writeChars(xmlString, chan, "\"", 1);
  2804   2809           }
  2805   2810           writeChars(xmlString, chan, "?>\n", 3);
  2806   2811       }
  2807   2812       if (node->nodeType == DOCUMENT_NODE) {
         2813  +        isDoc = 1;
  2808   2814           doc = (domDocument*) node;
  2809   2815           if (outputFlags & SERIALIZE_DOCTYPE_DECLARATION
  2810   2816               && doc->documentElement) {
  2811   2817               writeChars(xmlString, chan, "<!DOCTYPE ", 10);
  2812   2818               writeChars(xmlString, chan, doc->documentElement->nodeName, -1);
  2813   2819               if (   doc->doctype 
  2814   2820                   && doc->doctype->systemId
................................................................................
  2830   2836                       writeChars(xmlString, chan, doc->doctype->internalSubset,
  2831   2837                                  -1);
  2832   2838                       writeChars(xmlString, chan, "]", 1);
  2833   2839                   }
  2834   2840               }
  2835   2841               writeChars(xmlString, chan, ">\n", 2);
  2836   2842           }
  2837         -        child = doc->rootNode->firstChild;
  2838         -        while (child) {
  2839         -            tcldom_treeAsXML(xmlString, child, indent, level, doIndent, chan,
  2840         -                             NULL, 0, outputFlags, indentAttrs);
  2841         -            child = child->nextSibling;
  2842         -        }
  2843         -        return;
  2844         -    }
  2845         -
  2846         -    if (node->nodeType == TEXT_NODE) {
  2847         -        if (cdataChild) {
  2848         -            writeChars(xmlString, chan, "<![CDATA[", 9);
  2849         -            i = 0;
  2850         -            start = p = ((domTextNode*)node)->nodeValue;
  2851         -            while (i < ((domTextNode*)node)->valueLength) {
  2852         -                if (*p == ']') {
  2853         -                    p++; i++;;
  2854         -                    if (i >= ((domTextNode*)node)->valueLength) break;
         2843  +        node = doc->rootNode->firstChild;
         2844  +    }
         2845  +    if (outputFlags & SERIALIZE_INDENT_WITH_TAB) {
         2846  +        indBuf = "\t";
         2847  +        indBufCount = 1;
         2848  +    } else {
         2849  +        indBuf = "        ";
         2850  +        indBufCount = indent;
         2851  +    }
         2852  +    if (outputFlags & SERIALIZE_INDENT_ATTR_WITH_TAB) {
         2853  +        attindBuf = "\t";
         2854  +        attindBufCount = 1;
         2855  +    } else {
         2856  +        attindBuf = "        ";
         2857  +        attindBufCount = indentAttrs;
         2858  +    }
         2859  +    while (node) {
         2860  +        switch (node->nodeType) {
         2861  +        case TEXT_NODE:
         2862  +            if (cdataChild) {
         2863  +                writeChars(xmlString, chan, "<![CDATA[", 9);
         2864  +                i = 0;
         2865  +                start = p = ((domTextNode*)node)->nodeValue;
         2866  +                while (i < ((domTextNode*)node)->valueLength) {
  2855   2867                       if (*p == ']') {
  2856   2868                           p++; i++;;
  2857   2869                           if (i >= ((domTextNode*)node)->valueLength) break;
  2858         -                        if (*p == '>') {
  2859         -                            writeChars(xmlString, chan, start, p-start);
  2860         -                            writeChars(xmlString, chan, "]]><![CDATA[>", 13);
  2861         -                            start = p+1;
         2870  +                        if (*p == ']') {
         2871  +                            p++; i++;;
         2872  +                            if (i >= ((domTextNode*)node)->valueLength) break;
         2873  +                            if (*p == '>') {
         2874  +                                writeChars(xmlString, chan, start, p-start);
         2875  +                                writeChars(xmlString, chan, "]]><![CDATA[>", 13);
         2876  +                                start = p+1;
         2877  +                            }
  2862   2878                           }
  2863   2879                       }
         2880  +                    p++; i++;;
  2864   2881                   }
  2865         -                p++; i++;;
         2882  +                writeChars(xmlString, chan, start, p-start);
         2883  +                writeChars(xmlString, chan, "]]>", 3);
         2884  +            } else {
         2885  +                if (node->nodeFlags & DISABLE_OUTPUT_ESCAPING) {
         2886  +                    writeChars(xmlString, chan, ((domTextNode*)node)->nodeValue,
         2887  +                               ((domTextNode*)node)->valueLength);
         2888  +                } else {
         2889  +                    tcldom_AppendEscaped(xmlString, chan,
         2890  +                                         ((domTextNode*)node)->nodeValue,
         2891  +                                         ((domTextNode*)node)->valueLength,
         2892  +                                         outputFlags);
         2893  +                }
  2866   2894               }
  2867         -            writeChars(xmlString, chan, start, p-start);
         2895  +            break;
         2896  +
         2897  +        case CDATA_SECTION_NODE:
         2898  +            writeChars(xmlString, chan, "<![CDATA[", 9);
         2899  +            writeChars(xmlString, chan, ((domTextNode*)node)->nodeValue,
         2900  +                       ((domTextNode*)node)->valueLength);
  2868   2901               writeChars(xmlString, chan, "]]>", 3);
  2869         -        } else {
  2870         -            if (node->nodeFlags & DISABLE_OUTPUT_ESCAPING) {
  2871         -                writeChars(xmlString, chan, ((domTextNode*)node)->nodeValue,
  2872         -                           ((domTextNode*)node)->valueLength);
  2873         -            } else {
  2874         -                tcldom_AppendEscaped(xmlString, chan,
  2875         -                                     ((domTextNode*)node)->nodeValue,
  2876         -                                     ((domTextNode*)node)->valueLength,
  2877         -                                     outputFlags);
  2878         -            }
  2879         -        }
  2880         -        return;
  2881         -    }
  2882         -
  2883         -    if (node->nodeType == CDATA_SECTION_NODE) {
  2884         -        writeChars(xmlString, chan, "<![CDATA[", 9);
  2885         -        writeChars(xmlString, chan, ((domTextNode*)node)->nodeValue,
  2886         -                                    ((domTextNode*)node)->valueLength);
  2887         -        writeChars(xmlString, chan, "]]>", 3);
  2888         -        return;
  2889         -    }
  2890         -
  2891         -    if ((indent != -1) && doIndent) {
  2892         -        if (outputFlags & SERIALIZE_INDENT_WITH_TAB) {
  2893         -            for(i=0; i<level; i++) {
  2894         -                writeChars(xmlString, chan, "\t", 1);
  2895         -            }
  2896         -        } else {
  2897         -            for(i=0; i<level; i++) {
  2898         -                writeChars(xmlString, chan, "        ", indent);
  2899         -            }
  2900         -        }
  2901         -    }
  2902         -
  2903         -    if (node->nodeType == COMMENT_NODE) {
  2904         -        writeChars(xmlString, chan, "<!--", 4);
  2905         -        writeChars(xmlString, chan, ((domTextNode*)node)->nodeValue,
  2906         -                                    ((domTextNode*)node)->valueLength);
  2907         -        writeChars(xmlString, chan, "-->", 3);
  2908         -        if (indent != -1) writeChars (xmlString, chan, "\n", 1);
  2909         -        return;
  2910         -    }
  2911         -
  2912         -    if (node->nodeType == PROCESSING_INSTRUCTION_NODE) {
  2913         -        writeChars(xmlString, chan, "<?", 2);
  2914         -        writeChars(xmlString, chan, 
  2915         -                    ((domProcessingInstructionNode*)node)->targetValue,
  2916         -                    ((domProcessingInstructionNode*)node)->targetLength);
  2917         -        writeChars(xmlString, chan, " ", 1);
  2918         -        writeChars(xmlString, chan, 
  2919         -                   ((domProcessingInstructionNode*)node)->dataValue,
  2920         -                   ((domProcessingInstructionNode*)node)->dataLength);
  2921         -        writeChars(xmlString, chan, "?>", 2);
  2922         -        if (indent != -1) writeChars (xmlString, chan, "\n", 1);
  2923         -        return;
  2924         -    }
  2925         -
  2926         -    writeChars(xmlString, chan, "<", 1);
  2927         -    writeChars(xmlString, chan, node->nodeName, -1);
  2928         -
  2929         -    attrs = node->firstAttr;
  2930         -    while (attrs) {
  2931         -        if (indentAttrs > -1) {
  2932         -            writeChars(xmlString, chan, "\n", 1);
  2933         -            if ((indent != -1) && doIndent) {
  2934         -                if (outputFlags & SERIALIZE_INDENT_WITH_TAB) {
  2935         -                    for(i=0; i<level; i++) {
  2936         -                        writeChars(xmlString, chan, "\t", 1);
  2937         -                    }
  2938         -                } else {
  2939         -                    for(i=0; i<level; i++) {
  2940         -                        writeChars(xmlString, chan, "        ", indent);
  2941         -                    }
  2942         -                }
  2943         -                if (outputFlags & SERIALIZE_INDENT_ATTR_WITH_TAB) {
  2944         -                    writeChars(xmlString, chan, "\t", 1);
  2945         -                } else {
  2946         -                    writeChars(xmlString, chan, "        ", indentAttrs);
  2947         -                }
  2948         -            }
  2949         -        } else {
         2902  +            break;
         2903  +
         2904  +        case COMMENT_NODE:
         2905  +            if (indent != -1) {
         2906  +                for(i=0; i<level; i++) {
         2907  +                    writeChars(xmlString, chan, indBuf, indBufCount);
         2908  +                }
         2909  +            }
         2910  +            writeChars(xmlString, chan, "<!--", 4);
         2911  +            writeChars(xmlString, chan, ((domTextNode*)node)->nodeValue,
         2912  +                       ((domTextNode*)node)->valueLength);
         2913  +            writeChars(xmlString, chan, "-->", 3);
         2914  +            if (indent != -1) writeChars (xmlString, chan, "\n", 1);
         2915  +            break;
         2916  +        
         2917  +        case PROCESSING_INSTRUCTION_NODE:
         2918  +            if (indent != -1) {
         2919  +                for(i=0; i<level; i++) {
         2920  +                    writeChars(xmlString, chan, indBuf, indBufCount);
         2921  +                }
         2922  +            }
         2923  +            writeChars(xmlString, chan, "<?", 2);
         2924  +            writeChars(xmlString, chan, 
         2925  +                       ((domProcessingInstructionNode*)node)->targetValue,
         2926  +                       ((domProcessingInstructionNode*)node)->targetLength);
  2950   2927               writeChars(xmlString, chan, " ", 1);
  2951         -        }
  2952         -        writeChars(xmlString, chan, attrs->nodeName, -1);
  2953         -        writeChars(xmlString, chan, "=\"", 2);
  2954         -        tcldom_AppendEscaped(xmlString, chan, attrs->nodeValue, 
  2955         -                             attrs->valueLength,
  2956         -                             outputFlags | SERIALIZE_FOR_ATTR);
  2957         -        writeChars(xmlString, chan, "\"", 1);
  2958         -        attrs = attrs->nextSibling;
  2959         -    }
  2960         -
  2961         -    hasElements = 0;
  2962         -    first       = 1;
  2963         -    doIndent    = 1;
  2964         -
  2965         -    if (node->nodeType == ELEMENT_NODE) {
  2966         -        cdataChild = 0;
  2967         -        if (node->ownerDocument->doctype
  2968         -            && node->ownerDocument->doctype->cdataSectionElements) {
  2969         -            if (node->namespace) {
  2970         -                Tcl_DStringInit (&dStr);
  2971         -                Tcl_DStringAppend (&dStr, domNamespaceURI(node), -1);
  2972         -                Tcl_DStringAppend (&dStr, ":", 1);
  2973         -                domSplitQName (node->nodeName, prefix, &localName);
  2974         -                Tcl_DStringAppend (&dStr, localName, -1);
  2975         -                h = Tcl_FindHashEntry (
  2976         -                    node->ownerDocument->doctype->cdataSectionElements,
  2977         -                    Tcl_DStringValue (&dStr));
  2978         -                Tcl_DStringFree (&dStr);
  2979         -            } else {
  2980         -                h = Tcl_FindHashEntry (
  2981         -                    node->ownerDocument->doctype->cdataSectionElements,
  2982         -                    node->nodeName);
  2983         -            }
  2984         -            if (h) {
  2985         -                cdataChild = 1;
  2986         -            }
  2987         -        }
  2988         -        child = node->firstChild;
  2989         -        while (child != NULL) {
  2990         -
  2991         -            if (  (child->nodeType == ELEMENT_NODE)
  2992         -                ||(child->nodeType == PROCESSING_INSTRUCTION_NODE)
  2993         -                ||(child->nodeType == COMMENT_NODE) )
         2928  +            writeChars(xmlString, chan, 
         2929  +                       ((domProcessingInstructionNode*)node)->dataValue,
         2930  +                       ((domProcessingInstructionNode*)node)->dataLength);
         2931  +            writeChars(xmlString, chan, "?>", 2);
         2932  +            if (indent != -1) writeChars (xmlString, chan, "\n", 1);
         2933  +            break;
         2934  +
         2935  +        case ELEMENT_NODE:
         2936  +            if (indent != -1 &&
         2937  +                (node->previousSibling == NULL ||
         2938  +                 ((node->previousSibling->nodeType == ELEMENT_NODE) ||
         2939  +                  (node->previousSibling->nodeType == PROCESSING_INSTRUCTION_NODE) ||
         2940  +                  (node->previousSibling->nodeType == COMMENT_NODE)))
         2941  +                )
  2994   2942               {
  2995         -                hasElements = 1;
         2943  +                for(i=0; i<level; i++) {
         2944  +                    writeChars(xmlString, chan, indBuf, indBufCount);
         2945  +                }
  2996   2946               }
  2997         -            if (first) {
         2947  +            writeChars(xmlString, chan, "<", 1);
         2948  +            writeChars(xmlString, chan, node->nodeName, -1);
         2949  +            
         2950  +            attrs = node->firstAttr;
         2951  +            while (attrs) {
         2952  +                if (indentAttrs > -1) {
         2953  +                    writeChars(xmlString, chan, "\n", 1);
         2954  +                    if (indent != -1) {
         2955  +                        for(i=0; i<level; i++) {
         2956  +                            writeChars(xmlString, chan, indBuf, indBufCount);
         2957  +                        }
         2958  +                        writeChars(xmlString, chan, attindBuf, attindBufCount);
         2959  +                    }
         2960  +                } else {
         2961  +                    writeChars(xmlString, chan, " ", 1);
         2962  +                }
         2963  +                writeChars(xmlString, chan, attrs->nodeName, -1);
         2964  +                writeChars(xmlString, chan, "=\"", 2);
         2965  +                tcldom_AppendEscaped(xmlString, chan, attrs->nodeValue, 
         2966  +                                     attrs->valueLength,
         2967  +                                     outputFlags | SERIALIZE_FOR_ATTR);
         2968  +                writeChars(xmlString, chan, "\"", 1);
         2969  +                attrs = attrs->nextSibling;
         2970  +            }
         2971  +
         2972  +            if (node->firstChild) {
  2998   2973                   writeChars(xmlString, chan, ">", 1);
  2999         -                if ((indent != -1) && hasElements) {
         2974  +                if (indent != -1
         2975  +                    && (  (node->firstChild->nodeType == ELEMENT_NODE)
         2976  +                        ||(node->firstChild->nodeType == PROCESSING_INSTRUCTION_NODE)
         2977  +                        ||(node->firstChild->nodeType == COMMENT_NODE) )
         2978  +                    ) {
  3000   2979                       writeChars(xmlString, chan, "\n", 1);
  3001   2980                   }
  3002         -            }
  3003         -            first = 0;
  3004         -            tcldom_treeAsXML(xmlString, child, indent, level+1, doIndent,
  3005         -                             chan, NULL, cdataChild, outputFlags, indentAttrs);
  3006         -            doIndent = 0;
  3007         -            if (  (child->nodeType == ELEMENT_NODE)
  3008         -                ||(child->nodeType == PROCESSING_INSTRUCTION_NODE)
  3009         -                ||(child->nodeType == COMMENT_NODE) )
  3010         -            {
  3011         -               doIndent = 1;
  3012         -            }
  3013         -            child = child->nextSibling;
  3014         -        }
  3015         -    }
  3016         -
  3017         -    if (first) {
  3018         -        if (indent != -1) {
  3019         -            if (outputFlags & SERIALIZE_NO_EMPTY_ELEMENT_TAG) {
  3020         -                writeChars (xmlString, chan, "></", 3);
  3021         -                writeChars(xmlString, chan, node->nodeName, -1);
  3022         -                writeChars(xmlString, chan, ">\n", 2);
  3023         -            } else {
  3024         -                writeChars(xmlString, chan, "/>\n", 3);
  3025         -            }
  3026         -        } else {
  3027         -            if (outputFlags & SERIALIZE_NO_EMPTY_ELEMENT_TAG) {
  3028         -                writeChars (xmlString, chan, "></", 3);
  3029         -                writeChars(xmlString, chan, node->nodeName, -1);
  3030         -                writeChars(xmlString, chan, ">", 1);
  3031         -            } else {
  3032         -                writeChars(xmlString, chan, "/>",   2);
  3033         -            }
  3034         -        }
  3035         -    } else {
  3036         -        if ((indent != -1) && hasElements) {
  3037         -            if (outputFlags & SERIALIZE_INDENT_WITH_TAB) {
  3038         -                for(i=0; i<level; i++) {
  3039         -                    writeChars(xmlString, chan, "\t", 1);
  3040         -                }
  3041         -            } else {
  3042         -                for(i=0; i<level; i++) {
  3043         -                    writeChars(xmlString, chan, "        ", indent);
  3044         -                }
  3045         -            }
  3046         -        }
  3047         -        writeChars (xmlString, chan, "</", 2);
  3048         -        writeChars(xmlString, chan, node->nodeName, -1);
  3049         -        if (indent != -1) {
  3050         -            writeChars(xmlString, chan, ">\n", 2);
  3051         -        } else {
  3052         -            writeChars(xmlString, chan, ">",   1);
  3053         -        }
         2981  +                cdataChild = 0;
         2982  +                if (node->ownerDocument->doctype
         2983  +                    && node->ownerDocument->doctype->cdataSectionElements) {
         2984  +                    if (node->namespace) {
         2985  +                        Tcl_DStringInit (&dStr);
         2986  +                        Tcl_DStringAppend (&dStr, domNamespaceURI(node), -1);
         2987  +                        Tcl_DStringAppend (&dStr, ":", 1);
         2988  +                        domSplitQName (node->nodeName, prefix, &localName);
         2989  +                        Tcl_DStringAppend (&dStr, localName, -1);
         2990  +                        h = Tcl_FindHashEntry (
         2991  +                            node->ownerDocument->doctype->cdataSectionElements,
         2992  +                            Tcl_DStringValue (&dStr));
         2993  +                        Tcl_DStringFree (&dStr);
         2994  +                    } else {
         2995  +                        h = Tcl_FindHashEntry (
         2996  +                            node->ownerDocument->doctype->cdataSectionElements,
         2997  +                            node->nodeName);
         2998  +                    }
         2999  +                    if (h) {
         3000  +                        cdataChild = 1;
         3001  +                    }
         3002  +                }
         3003  +                if (level < STATIC_STACK_SIZE) {
         3004  +                    staticStack[level].node = node;
         3005  +                    staticStack[level].cdata = cdataChild;
         3006  +                } else {
         3007  +                    if (level >= STATIC_STACK_SIZE + dynStackSize) {
         3008  +                        if (dynStackSize) {
         3009  +                            dynStack = (asXMLStack *)
         3010  +                                REALLOC (dynStack,
         3011  +                                         sizeof(asXMLStack)*dynStackSize*2);
         3012  +                            dynStackSize *= 2;
         3013  +                        } else {
         3014  +                            dynStack = (asXMLStack *)
         3015  +                                MALLOC (sizeof(asXMLStack)*STATIC_STACK_SIZE);
         3016  +                            dynStackSize = STATIC_STACK_SIZE;
         3017  +                        }
         3018  +                    }
         3019  +                    dynStack[level-STATIC_STACK_SIZE].node = node;
         3020  +                    dynStack[level-STATIC_STACK_SIZE].cdata = cdataChild;
         3021  +                }
         3022  +                level++;
         3023  +                node = node->firstChild;
         3024  +                continue;
         3025  +            } else {
         3026  +                if (indent != -1 &&
         3027  +                    (node->nextSibling == NULL ||
         3028  +                     ((node->nextSibling->nodeType == ELEMENT_NODE) ||
         3029  +                      (node->nextSibling->nodeType == PROCESSING_INSTRUCTION_NODE) ||
         3030  +                      (node->nextSibling->nodeType == COMMENT_NODE)))
         3031  +                    )
         3032  +                {
         3033  +                    if (outputFlags & SERIALIZE_NO_EMPTY_ELEMENT_TAG) {
         3034  +                        writeChars (xmlString, chan, "></", 3);
         3035  +                        writeChars(xmlString, chan, node->nodeName, -1);
         3036  +                        writeChars(xmlString, chan, ">\n", 2);
         3037  +                    } else {
         3038  +                        writeChars(xmlString, chan, "/>\n", 3);
         3039  +                    }
         3040  +                } else {
         3041  +                    if (outputFlags & SERIALIZE_NO_EMPTY_ELEMENT_TAG) {
         3042  +                        writeChars (xmlString, chan, "></", 3);
         3043  +                        writeChars(xmlString, chan, node->nodeName, -1);
         3044  +                        writeChars(xmlString, chan, ">", 1);
         3045  +                    } else {
         3046  +                        writeChars(xmlString, chan, "/>",   2);
         3047  +                    }
         3048  +                }
         3049  +            }
         3050  +        default:
         3051  +            /* Does not happen */
         3052  +            ;
         3053  +        }
         3054  +        
         3055  +        if (level == 0) {
         3056  +            if (isDoc) {
         3057  +                node = node->nextSibling;
         3058  +            } else {
         3059  +                break;
         3060  +            }
         3061  +        } else {
         3062  +            if (node->nextSibling) {
         3063  +                node = node->nextSibling;
         3064  +            } else {
         3065  +                while (1) {
         3066  +                    level--;
         3067  +                    if (level < STATIC_STACK_SIZE) {
         3068  +                        node = staticStack[level].node;
         3069  +                        cdataChild = staticStack[level].cdata;
         3070  +                    } else {
         3071  +                        node = dynStack[level-STATIC_STACK_SIZE].node;
         3072  +                        cdataChild = dynStack[level-STATIC_STACK_SIZE].cdata;
         3073  +                    }
         3074  +                    if (indent != -1 
         3075  +                        && (   node->firstChild->nodeType == ELEMENT_NODE
         3076  +                               || node->firstChild->nodeType == PROCESSING_INSTRUCTION_NODE
         3077  +                               || node->firstChild->nodeType == COMMENT_NODE )
         3078  +                        ) {
         3079  +                        for(i=0; i<level; i++) {
         3080  +                            writeChars(xmlString, chan, indBuf, indBufCount);
         3081  +                        }
         3082  +                    }
         3083  +                    writeChars (xmlString, chan, "</", 2);
         3084  +                    writeChars(xmlString, chan, node->nodeName, -1);
         3085  +                    if (indent != -1) {
         3086  +                        writeChars(xmlString, chan, ">\n", 2);
         3087  +                    } else {
         3088  +                        writeChars(xmlString, chan, ">",   1);
         3089  +                    }
         3090  +                    if (level > 0) {
         3091  +                        if (node->nextSibling) {
         3092  +                            cdataChild = staticStack[level-1].cdata;
         3093  +                            node = node->nextSibling;
         3094  +                            break;
         3095  +                        } else {
         3096  +                            continue;
         3097  +                        }
         3098  +                    } else {
         3099  +                        if (isDoc) {
         3100  +                            node = node->nextSibling;
         3101  +                        } else {
         3102  +                            node = NULL;
         3103  +                        }
         3104  +                        break;
         3105  +                    }
         3106  +                }
         3107  +            }
         3108  +        }
         3109  +    }
         3110  +    if (dynStackSize) {
         3111  +        FREE (dynStack);
  3054   3112       }
  3055   3113   }
  3056   3114   
  3057   3115   /*----------------------------------------------------------------------------
  3058   3116   |   tcldom_AppendEscapedJSON
  3059   3117   |
  3060   3118   \---------------------------------------------------------------------------*/
................................................................................
  3490   3548   static int serializeAsXML (
  3491   3549       domNode    *node,
  3492   3550       Tcl_Interp *interp,
  3493   3551       int         objc,
  3494   3552       Tcl_Obj    *const objv[]
  3495   3553   )
  3496   3554   {
  3497         -    char          *channelId, prefix[MAX_PREFIX_LEN];
  3498         -    const char    *localName;
         3555  +    char          *channelId;
  3499   3556       int            indent, mode, bool;
  3500   3557       int            outputFlags = 0;
  3501         -    int            optionIndex, cdataChild;
         3558  +    int            optionIndex;
  3502   3559       Tcl_Obj       *resultPtr, *encString = NULL;
  3503   3560       Tcl_Channel    chan = (Tcl_Channel) NULL;
  3504         -    Tcl_HashEntry *h;
  3505         -    Tcl_DString    dStr;
  3506   3561       int            indentAttrs = -1;
  3507   3562   
  3508   3563       static const char *asXMLOptions[] = {
  3509   3564           "-indent", "-channel", "-escapeNonASCII", "-doctypeDeclaration",
  3510   3565           "-xmlDeclaration", "-encString", "-escapeAllQuot", "-indentAttrs",
  3511   3566           "-nogtescape", "-noEmptyElementTag",
  3512   3567           NULL
................................................................................
  3670   3725               break;
  3671   3726           }
  3672   3727       }
  3673   3728       if (indent > 8)  indent = 8;
  3674   3729       if (indent < -1) indent = -1;
  3675   3730   
  3676   3731       resultPtr = Tcl_NewStringObj("", 0);
  3677         -    cdataChild = 0;
  3678         -    if (node->nodeType == ELEMENT_NODE
  3679         -        && node->ownerDocument->doctype 
  3680         -        && node->ownerDocument->doctype->cdataSectionElements) {
  3681         -        if (node->namespace) {
  3682         -            Tcl_DStringInit (&dStr);
  3683         -            Tcl_DStringAppend (&dStr, domNamespaceURI(node), -1);
  3684         -            Tcl_DStringAppend (&dStr, ":", 1);
  3685         -            domSplitQName (node->nodeName, prefix, &localName);
  3686         -            Tcl_DStringAppend (&dStr, localName, -1);
  3687         -            h = Tcl_FindHashEntry (
  3688         -                node->ownerDocument->doctype->cdataSectionElements,
  3689         -                Tcl_DStringValue (&dStr));
  3690         -            Tcl_DStringFree (&dStr);
  3691         -        } else {
  3692         -            h = Tcl_FindHashEntry (
  3693         -                node->ownerDocument->doctype->cdataSectionElements,
  3694         -                node->nodeName);
  3695         -        }
  3696         -        if (h) {
  3697         -            cdataChild = 1;
  3698         -        }
  3699         -    }
  3700         -    tcldom_treeAsXML(resultPtr, node, indent, 0, 1, chan, encString,
  3701         -                     cdataChild, outputFlags, indentAttrs);
         3732  +    tcldom_treeAsXML(resultPtr, node, indent, chan, encString,
         3733  +                     outputFlags, indentAttrs);
  3702   3734       Tcl_SetObjResult(interp, resultPtr);
  3703   3735       if (encString) {
  3704   3736           Tcl_DecrRefCount(encString);
  3705   3737       }
  3706   3738       return TCL_OK;
  3707   3739   cleanup:
  3708   3740       if (encString) {

Changes to tests/domDoc.test.

   367    367       $doc delete
   368    368       set result
   369    369   } {<html
   370    370   ><body
   371    371   ><p
   372    372   >boo</p></body></html>}
   373    373   
          374  +test domDoc-1.39 {asXML -indent tabs w/ comment} {
          375  +    set doc [dom parse {<doc><a><!-- comment one --><b/><!-- comment two --></a><!-- comment three --></doc>}]
          376  +    set result [$doc asXML -indent tabs]
          377  +    $doc delete
          378  +    set result
          379  +} "<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"
          380  +
          381  +test domDoc-1.40 {asXML -indent tabs w/ processing-instruction} {
          382  +    set doc [dom parse {<doc><a><?p 1?><b/><?p 2?></a><?p 3?></doc>}]
          383  +    set result [$doc asXML -indent tabs]
          384  +    $doc delete
          385  +    set result
          386  +} "<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"
          387  +
   374    388   set doc [dom parse <root/>]
   375    389   
   376    390   test domDoc-2.1 {publicId - no publicId there} {
   377    391       $doc publicId
   378    392   } {}
   379    393   
   380    394   test domDoc-2.2 {systemId - no systemId there} {