lcPI = loXML.createProcessingInstruction("xml", "version='1.0'") loXML.replaceChild(lcPI, loXML.childNodes.item(0))You can 'pretty-print' the XML using this code:
* Function FormatXML(toXML, tnTabLevel) * FormatXML() accepts an XML file/string and returns a string * with all the nodes indented. (It's PrettyPrint for XML) * Simon Ferguson - EPS Software LPARAMETERS toXML, tnTabLevel IF EMPTY(tnTabLevel) tnTabLevel = 0 ENDIF LOCAL llMixedTextNode, llHasOnlyATextNode, i, lcFormatXML, lcTempXML lcFormatXML = "" lcTempXML = "" && VFP 'feature' - Necessary to hold temp XML before recursion of more than 4 levels ** #DEFINE TAB CHR(9) && Default IE format #DEFINE TAB SPACE(2) && My preferred format #DEFINE CR CHR(13) #DEFINE CRLF CHR(13)+CHR(10) #DEFINE DQ CHR(34) && doublequote #DEFINE SQ CHR(39) && singlequote #DEFINE NODE_ELEMENT 1 #DEFINE NODE_ATTRIBUTE 2 #DEFINE NODE_TEXT 3 #DEFINE NODE_CDATA_SECTION 4 #DEFINE NODE_ENTITY 6 #DEFINE NODE_COMMENT 8 #DEFINE NODE_DOCUMENT 9 #DEFINE NODE_DOCUMENT_FRAGMENT 11 ** If we passed in a string, convert to DOM object IF VARTYPE(toXML) = "C" LOCAL loXML loXML = CREATEOBJECT("MSXML.DomDocument") toXML = loXML.LoadXML(toXML) RELEASE loXML ENDIF WITH toXML DO CASE CASE .nodeType = NODE_DOCUMENT OR .nodeType = NODE_DOCUMENT_FRAGMENT * All child nodes of the document should be at the same level * Just iterate over them and recurse with no indent FOR i = 0 TO .childNodes.Length- 1 lcTempXML = lcFormatXML lcFormatXML = lcTempXML + FormatXML(.childNodes(i)) NEXT i CASE .nodeType = NODE_TEXT * Should render the same way the default IE stylesheet does for mixed content * Figure out if we're in some mixed content * If this text node has any siblings it's in mixed content llMixedTextNode = (.parentNode.childNodes.LENGTH > 1) * If mixed, indent this string IF llMixedTextNode lcFormatXML = REPLICATE(TAB, tnTabLevel) ENDIF * Strip out any tabs and carriage returns from the text lcFormatXML = lcFormatXML + TRIM(STRTRAN(STRTRAN(.xml, CRLF, SPACE(1)), TAB, SPACE(1))) * If mixed, add carriage return IF llMixedTextNode lcFormatXML = lcFormatXML + CRLF ENDIF CASE .nodeType = NODE_ELEMENT IF .hasChildNodes * If the node has only one child and that child is text * don't add carriage return after opening tag llHasOnlyATextNode = (.childNodes(0).nodeType = NODE_TEXT) AND (.childNodes.Length = 1) ENDIF * Open the start tag lcFormatXML = REPLICATE(TAB, tnTabLevel) + "<" + .nodeName * Recurse over the attributes FOR i = 0 TO .Attributes.Length - 1 lcTempXML = lcFormatXML lcFormatXML = lcTempXML + FormatXML(.Attributes(i)) NEXT i * Properly close the start tag based on node's contents IF NOT .hasChildNodes * No child nodes so it's an empty element lcFormatXML = lcFormatXML + "/>" + CRLF ELSE IF llHasOnlyATextNode * Has only text for children - don't add carriage return lcFormatXML = lcFormatXML + ">" ELSE * Has child elements - add carriage return lcFormatXML = lcFormatXML + ">" + CRLF ENDIF * Recurse if there's children FOR i = 0 TO .childNodes.Length - 1 lcTempXML = lcFormatXML lcFormatXML = lcTempXML + FormatXML(.childNodes(i), tnTabLevel + 1) NEXT i * Properly indent and add the end tag IF NOT llHasOnlyATextNode lcFormatXML = lcFormatXML + REPLICATE(TAB, tnTabLevel) ENDIF lcFormatXML = lcFormatXML + "</" + .nodeName + ">" + CRLF ENDIF CASE .nodeType = NODE_COMMENT OR .nodeType = NODE_CDATA_SECTION * If comment is on more than one line don't indent IF OCCURS(CR, .xml) = 0 lcFormatXML = REPLICATE(TAB, tnTabLevel) ENDIF lcFormatXML = lcFormatXML + .xml + CRLF CASE .nodeType = NODE_ATTRIBUTE * If there are double quotes in the attribute, use single quotes to surround the attribute value IF OCCURS(DQ, .text) > 0 lcFormatXML = SPACE(1) + .nodeName + "=" + SQ + .text + SQ ELSE lcFormatXML = SPACE(1) + .nodeName + "=" + DQ + .text + DQ ENDIF CASE .nodeType = NODE_ENTITY * Don't expand entities OTHERWISE * All other node types should just return their xml * These include - entity refs, pi's, notations, doctypes lcFormatXML = REPLICATE(TAB, tnTabLevel) + .xml + CRLF ENDCASE ENDWITH RETURN lcFormatXML