Solved

Microsoft XML DOM output has no CR/LF

Posted on 2001-06-14
16
2,334 Views
Last Modified: 2013-11-19
I am using the MS XML DOM to create a document, and am then saving it with a simple document.save method to an XML file on disk. When the XML file is looked at in a text editor, I want to see something neat like this:

<whatever>
  <something>data</something>
  <somethingelse>data</somethingelse>
</whatever>

Instead, what the MS DOM is saving is this:

<whatever><something>data</something><somethingelse>data</somethingelse></whatever>

Everything is output on a single line with no CR/LF anywhere, making it totally unreadable - especially on a 20K XML file, where everything is crammed on a single line.

I've searched for a parameter to change this behavior, with no luck. Anyone have an idea?
0
Comment
Question by:ScottNero
  • 4
  • 3
  • 2
  • +5
16 Comments
 
LVL 2

Expert Comment

by:MicOfLZ
Comment Utility
load the file into CUESoft's Exml Editor (freeware) - it will structure the file in the "source view".

you can get it at:

http://www.cuesoft.com

Hope this helps

Cheers
MicOfLZ
0
 
LVL 1

Author Comment

by:ScottNero
Comment Utility
That's great for viewing it - I can do the same thing by opening it in IE. But what I need to do is to have the MS DOM write it out in a readable format in the first place.
0
 
LVL 4

Expert Comment

by:vindevogel
Comment Utility
we're using version 3 of the parser and we don't have that problem ....
0
 
LVL 2

Expert Comment

by:RickHalle
Comment Utility
xmldoc.preserveWhiteSpace = True

I think you need to set it to true right after creating the object but before adding anything
0
 
LVL 1

Author Comment

by:ScottNero
Comment Utility
No, I tried using the preserveWhiteSpace parameter, with no effect. That parameter is used to preserve white space inside the tags, I'm looking to create white space between different tags.

Here is some VB code to demonstrate what is happening. I have referenced MSXML3.DLL in the project.

  Dim XMLdoc As New MSXML2.DOMDocument30
  Dim root As IXMLDOMElement
  Dim newNode As IXMLDOMNode
  Dim Config As IXMLDOMNode
  Dim docFragment As IXMLDOMDocumentFragment
  Dim CfgVal As IXMLDOMElement
   
  Set root = XMLdoc.documentElement
 
  Set newNode = XMLdoc.createNode("processinginstruction", "xml", "")
  Set Config = XMLdoc.appendChild(newNode)

  XMLdoc.appendChild XMLdoc.createElement("Main")
     
  Set Config = XMLdoc.createNode(NODE_ELEMENT, "Node1", "")
  XMLdoc.lastChild.appendChild Config

  Set docFragment = XMLdoc.createDocumentFragment
 
  Set CfgVal = XMLdoc.createElement("Element1")
  CfgVal.Text = "This is element 1"
  docFragment.appendChild CfgVal
  Set CfgVal = XMLdoc.createElement("Element2")
  CfgVal.Text = "This is element 2"
  docFragment.appendChild CfgVal
 
  Config.appendChild docFragment
 
  XMLdoc.save "c:\temp\test.xml"

The XML file created by this code looks like the following. Everything except the version is crammed onto one line:

<?xml version="1.0"?>
<Main><Node1><Element1>This is element 1</Element1><Element2>This is element 2</Element2></Node1></Main>

0
 
LVL 6

Expert Comment

by:anthony_glenwright
Comment Utility
Put a line

  <xsl:output method="xml" indent="yes" />

or in your case it might be

  <xsl:output method="html" indent="yes" />
 
Just after the namespace declarations.
0
 
LVL 6

Expert Comment

by:anthony_glenwright
Comment Utility
Sorry, didnt read the question properly - that only works when you use XSL to create the document (since it's an XSL command!)
0
 
LVL 2

Expert Comment

by:MicOfLZ
Comment Utility
I think then you'll have to write a function that writes the DOM object to a textfile trough the filesystem object.

Cheers
MicOfLZ
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 15

Accepted Solution

by:
robbert earned 50 total points
Comment Utility
Hi, this is what I use.

Btw, you should always aim at an A grade, and a "Points for ..." question resulting in a B is not quite common :-)

------------------

Public Function FormatXML(ByRef objNode As MSXML2.IXMLDOMNode, _
Optional ByVal intTabLevel As Integer = 0, _
Optional ByVal strLineBreakChars As String = vbCrLf) As String
    On Error GoTo ErrHandler
   
    Dim blnMixedTextNode As Boolean
    Dim blnHasATextNodeOnly As Boolean
    Dim i As Integer

    With objNode
        Select Case .nodeType
        Case NODE_DOCUMENT, NODE_DOCUMENT_FRAGMENT
            ' all child nodes of the document should be at the same indent Level
            ' just iterate over them and recurse with 0 indent
            For i = 0 To .childNodes.length - 1
                FormatXML = FormatXML & FormatXML(.childNodes(i))
            Next i
       
        Case NODE_TEXT
            ' should render the same way the default IE5 stylesheet does for mixed content
            ' figure out if we're in some mixed content
            blnMixedTextNode = (.parentNode.childNodes.length > 1)  'if this text node has any siblings it's in mixed content

            ' if mixed indent this string
            If blnMixedTextNode Then FormatXML = String(intTabLevel, vbTab)
            ' we're gonna strip out any tabs and carriage returns from the Text
            FormatXML = FormatXML & Trim(Replace(Replace(.xml, strLineBreakChars, " "), vbTab, " "))
            ' if mixed add cariage return
            If blnMixedTextNode Then FormatXML = FormatXML & strLineBreakChars

        Case NODE_ELEMENT
            If .hasChildNodes Then
                ' if the node has only one child and that child is text we won't add carriage return after opening tag
                blnHasATextNodeOnly = (.childNodes(0).nodeType = NODE_TEXT) And (.childNodes.length = 1)
            End If
           
            ' open the start tag
            FormatXML = String(intTabLevel, vbTab) & "<" & .nodeName

            ' recurse over the attributes
            For i = 0 To .Attributes.length - 1
                FormatXML = FormatXML + FormatXML(.Attributes(i))
            Next i

            ' properly close the start tag based on node's contents
            If Not .hasChildNodes Then       ' no child nodes so it's an empty element
                FormatXML = FormatXML & "/>" & strLineBreakChars
               
            Else
                If blnHasATextNodeOnly Then    ' has only text for children - don't add carriage return
                    FormatXML = FormatXML & ">"
                Else                            ' has child elements - add carriage return
                    FormatXML = FormatXML & ">" & strLineBreakChars
                End If
               
                ' recurse if there's children
                For i = 0 To .childNodes.length - 1
                    FormatXML = FormatXML & FormatXML(.childNodes(i), intTabLevel + 1)
                Next i
               
                ' properly indent and add the end tag
                If Not blnHasATextNodeOnly Then FormatXML = FormatXML & String(intTabLevel, vbTab)
                FormatXML = FormatXML & "</" & .nodeName & ">" & strLineBreakChars
               
            End If
                   
        Case NODE_COMMENT, NODE_CDATA_SECTION
            ' if comment is on more than one line don't indent
            If InStr(1, .xml, vbCr) = 0 Then FormatXML = String(intTabLevel, vbTab)
            FormatXML = FormatXML & .xml & strLineBreakChars
       
        Case NODE_ATTRIBUTE
            ' if there are double quotes in the attribute use single quotes to surrond the attr value
            If InStr(1, .Text, Chr(34)) > 0 Then
                FormatXML = " " & .nodeName & "='" & .Text & "'"
            Else
                FormatXML = " " & .nodeName & "=" & Chr(34) & .Text & Chr(34)
            End If
       
        Case NODE_ENTITY
            ' and we would never want entites expanded
           
        Case Else
            ' all other node types should just return their xml (properly indented)
            ' these include - entity refs, pi's, notations, doctypes
            FormatXML = String(intTabLevel, vbTab) & .xml & strLineBreakChars
           
        End Select
    End With
   
    ' the msxml parser is using vbCrLf as line separator...
    If strLineBreakChars <> vbCrLf Then
        FormatXML = Replace(FormatXML, vbCrLf, strLineBreakChars)
    End If
   
    Exit Function
   
ErrHandler:
    Err.Raise Err.Number, Err.Source, Err.Description
End Function
0
 
LVL 2

Expert Comment

by:MicOfLZ
Comment Utility
hi

does my comment correspond to your question ?

MicOfLZ
0
 
LVL 1

Author Comment

by:ScottNero
Comment Utility
Your idea, and the code above basically circumvents the Microsoft DOM "save" method and does it itself, iterating through the tree and writing it out manually. I could do that, but I was kind of hoping for a kind of "xmldoc.crlf = True" thing. All of the MS examples show the code written out as formatted and indented nicely, so I'm wondering if there is still something I'm missing.
0
 
LVL 15

Expert Comment

by:robbert
Comment Utility
> All of the MS examples show the code written out as formatted and indented nicely, so I'm wondering if there is still something I'm missing.

Sure. You're missing that MSXML doesn't attempt to make the XML it produces readable. You need to make it human-readable, yourself. And please, give an A next time.
0
 
LVL 1

Expert Comment

by:Moondancer
Comment Utility
It's time to clean up this topic area and that means taking care of this question. Your options at this point are:

1. Award points to the Expert who provided an answer, or who helped you most. Do this by clicking on the "Accept Comment as Answer" button that lies above and to the right of the appropriate expert's name.

2. PAQ the question because the information might be useful to others, but was not useful to you. To use this option, you must state why the question is no longer useful to you, and the experts need to let me know if they feel that you're being unfair.

3.  Ask Community Support to help split points between participating experts.  Just comment here with details.

4.  Delete the question because it is of no value to you or to anyone else.  To use this option, you must state why the question is no longer useful to you, and the experts need to let me know if they feel that you're being unfair.

If you elect for option 2, 3 or 4, just post comment with details here and I'll take it from there.  We also request that you review any other open questions you might have and update/close them.  Display all your question history from your Member Profile to view details.

PLEASE DO NOT AWARD THE POINTS TO ME.
____________________________________________
---------->  Hi Experts:

In the event that the Asker does not respond, I would very much appreciate your opinions as to which Expert ought to receive points (if any) as a result of this question.  Likewise, you can also suggest that I PAQ or delete the question.

------------->  The ALL TOPICS link has been updated today to reflect all the new TAs.

Thank you everyone.

Moondancer :)
Community Support Moderator @ Experts Exchange
0
 
LVL 23

Expert Comment

by:b1xml2
Comment Utility
<review>

<recommendation>
award points to robbert and grade A
</recommendation>

<objection>
any objection should be raised within 7 days
</objection>

<reviewer>
b1xml2
</reviewer>

</review>
0
 
LVL 1

Author Comment

by:ScottNero
Comment Utility
Not quite what I was looking for, but the end result is the same.
0
 
LVL 23

Expert Comment

by:b1xml2
Comment Utility
thank you for finalising the question, Scott =)
0

Featured Post

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

Suggested Solutions

This article covers the basics of the Sass, which is a CSS extension language. You will learn about variables, mixins, and nesting.
Have you tried to learn about Unicode, UTF-8, and multibyte text encoding and all the articles are just too "academic" or too technical? This article aims to make the whole topic easy for just about anyone to understand.
Viewers will learn about the different types of variables in Java and how to declare them. Decide the type of variable desired: Put the keyword corresponding to the type of variable in front of the variable name: Use the equal sign to assign a v…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now