-
Indenting XML properly using MSXML4
Could you guys help me with a way to indent XML properly using MSXML4 and nodes (instead of using InStr to find < and />). I am looking for a clean and proper way to do it.
I currenly have something like this:
<PropertyBag><CProject name="TestProj1"><FileName>test.lfp</FileName></CProject></PropertyBag>
and I would like it to turn out like this:
Code:
<PropertyBag>
<CProject name="TestProj1">
<FileName>test.lfp</FileName>
</CProject>
</PropertyBag>
Notice how the inner-most node contents doesn't go on a new line. I think it looks better this way.
I have searched the forums and google and not found anything. I'm not good with MSXML so I don't even know where to start.
Also, having the option to use 4 spaces or tabs would be great.
Thanks a ton.
-
Re: Identing XML properly using MSXML4
I added [code][/code] tags around your XML so that your indenting shows up. I assume you are creating this XML file from VB. If so then as far as I know there is no good way to format the output so that it indents.
-
Re: Indenting XML properly using MSXML4
Oops, forgot the CODE tags.
How can there be no good way to do it in VB6?
I won't be passing a DOMDocument or whatever to do the function that does the indenting, I will be passing a string like I posted above. The class I am using (from vbAccelerator) sends me a string like I posted above and I need to indent it.
Here is the function they use to indent the XML (the comment at the top is the reason I am asking about a way to do it using MSXML.dll.
VB Code:
Private Function NiceXML(sXML As String) As String
Dim iOpenPos As Long
Dim iClosePos As Long
Dim iLastPos As Long
Dim iLevel As Long
Dim sLevelSpace As String
Dim sOut As String
' SPM: this is quick & dirty, it could fail on CDATA sections...
' to do it properly, use MSXML to enum the nodes instead.
iLastPos = 1
iOpenPos = InStr(iLastPos, sXML, "<")
If iOpenPos > 0 Then
If iOpenPos > 1 Then
sOut = sOut & Left$(sXML, iOpenPos)
End If
Do
iClosePos = InStr(iOpenPos, sXML, ">")
If iClosePos > 0 Then
If (Mid$(sXML, iOpenPos + 1, 1) = "/") Then
iLevel = iLevel - 1
If iLevel > 0 Then sLevelSpace = Space$(iLevel * 3) Else sLevelSpace = ""
sOut = sOut & vbCrLf & sLevelSpace & Mid$(sXML, iOpenPos, iClosePos - iOpenPos + 1) & vbCrLf
Else
sOut = sOut & sLevelSpace & Mid$(sXML, iOpenPos, iClosePos - iOpenPos + 1) & vbCrLf
iLevel = iLevel + 1
If iLevel > 0 Then sLevelSpace = Space$(iLevel * 3) Else sLevelSpace = ""
End If
iLastPos = iClosePos + 1
iOpenPos = InStr(iLastPos, sXML, "<")
If iOpenPos > iLastPos Then
sOut = sOut & sLevelSpace & Mid$(sXML, iLastPos, iOpenPos - iLastPos)
End If
End If
Loop While iOpenPos > 0
End If
If iLastPos > 0 And iLastPos < Len(sXML) Then
sOut = sOut & Mid$(sXML, iLastPos)
End If
NiceXML = sOut
End Function
-
Re: Indenting XML properly using MSXML4
I've seen similar code and as they point out there is at least one problem. I know of no way of doing the indenting via MSXML, however I'm not the last word on this. I do wonder however if there was an "enum the nodes" method then why didn't they use it?
-
Re: Indenting XML properly using MSXML4
I've only read one short begginers tutorial on using MSXML but I though there was a way to get the XML code and the text within it for a node. If you could get that couldn't you use the strucutre of the node and its parent's etc. to figure out how far tabbed it needs to be?
-
Re: Indenting XML properly using MSXML4
Yes you can and that is exactly what that code does, but when you add spaces or tabs the XML considers it data.
-
Re: Indenting XML properly using MSXML4
What if you stored it in a seperate string though? I mean looped through each node, use whatever property it is that returns the contents of the node AND the XML directly around it, then use the position of the node and the position of its parent to determine how many tabs out it should be, then tab it over that many, then store it in a seperate string and proceed to the next node?
What would the problem be with that?
-
Re: Indenting XML properly using MSXML4
Those tabs would still be in the XML though, right?
-
Re: Indenting XML properly using MSXML4
Here is a note on the subject.
-
Re: Indenting XML properly using MSXML4
Oh. I see what you are saying.
I wasn't refering to putting the tabs IN the XML. I meant just being able to format the XML with tabs and then save it to a file (so that if anyone opens the file it will be readable. I don't care if they are in the actual XML at all.
So now that we are on the same page, do you think it is possible or know how to do it? Possibly using the method I described in post #7?
PS - Reading the link you just posted would only be a problem if you tried to tab the inner-most element, but if you did it like this:
Code:
<parent>
<child1>
<child2a>value</child2a>
<child2b>another value</child2b>
</child1>
</parent>
Then I don't think any parsers would have trouble with that. I don't think it would matter if they did because the parser I am using to work with the XML is the only parser that will ever deal with it (most likely) and that parser ignores all the extra whitespace.
-
Re: Indenting XML properly using MSXML4
Why even try to read the XML? If it was supposed to be readable, it'd be saved as text.
-
Re: Indenting XML properly using MSXML4
Quote:
Originally Posted by dglienna
Why even try to read the XML? If it was supposed to be readable, it'd be saved as text.
Huh?
-
Re: Indenting XML properly using MSXML4
It's stored in a common format which makes it easy to transport. I don't think readablilty is a concern. I'm just saying that you would probably parse it before you try to read it, and do the formatting in there, rather than embed it in the xml code. XML could be parsed even if it was all on one line, as the tags are used to separate parts of the text.
-
Re: Indenting XML properly using MSXML4
Quote:
Originally Posted by dglienna
Why even try to read the XML? If it was supposed to be readable, it'd be saved as text.
Double huh?
XML is VERY readable and it is saved as text. Its like reading HTML, but easier. The biggest advantage to it is that is stores the data and can describe the data it stores. I open my iTumes XML library from time to time when I am looking for stuff or just want a good example of XML. I can read it easier than I can read HTML (because most HTML is written poorly).
-
Re: Indenting XML properly using MSXML4
dglienna is correct. All-on-one-line XML can be parsed by the DOM or other methods via code, but what we are talking about here (I think) is human readability.
-
Re: Indenting XML properly using MSXML4
Quote:
Originally Posted by dglienna
It's stored in a common format which makes it easy to transport. I don't think readablilty is a concern. I'm just saying that you would probably parse it before you try to read it, and do the formatting in there, rather than embed it in the xml code. XML could be parsed even if it was all on one line, as the tags are used to separate parts of the text.
Have you ever opened a VB .frm file in notepad? It is has a higharchial (sp?) structure. It is readable for the most part.
I see no reason not to make it readable (indented) unless you are dealing with a HUGE file and you are worries about the spaces/tabs taking up extra space.
-
Re: Indenting XML properly using MSXML4
Quote:
Originally Posted by MartinLiss
dglienna is correct. All-on-one-line XML can be parsed by the DOM or other methods via code, but what we are talking about here (I think) is human readability.
Yes we are taking about human readability. The only reason I brought up the parser not being able to read it with tabs is because I thought that is what the page you posted was talking about (but I only skimmed it).
-
Re: Indenting XML properly using MSXML4
So does anyone enough experience with XML to help me write some stuff using MSXML to loop through the nodes and indent indent them?
Even if someone could just show me how to loop through all the nodes recurssively, I could probably do the rest.
-
Re: Indenting XML properly using MSXML4
VB Code:
Option Explicit
Private oXMLDoc As MSXML2.DOMDocument40
Private Sub Form_Load()
Set oXMLDoc = New DOMDocument40
oXMLDoc.Load "MyXMLFilePath"
RecurseXML oXMLDoc
Set oXMLDoc = Nothing
End Sub
Public Function RecurseXML(ByRef oxmlNode As IXMLDOMNode)
Dim oxmlNodeList As IXMLDOMNodeList
Dim lngNodeIndex As Long
Debug.Print oxmlNode.nodeName ' Or whatever you want to do
Set oxmlNodeList = oxmlNode.childNodes
For lngNodeIndex = 0 To oxmlNodeList.length - 1
RecurseXML oxmlNodeList(lngNodeIndex)
Next
End Function
-
Re: Indenting XML properly using MSXML4
Thanks Marty. I will take a look at that and see what I can do. I will post if I come up with anything.
-
Re: Indenting XML properly using MSXML4
XML allows multilines. How will your app know what should be indented.
Think about it. It's probably not worth being readable by humans, just to look nice.
-
Re: Indenting XML properly using MSXML4
I really do think it is worth it. Maybe I am wrong though.
I have been trying to think of a way to get it to work and I just don't think it will without the use of instr and mid and stuff. Maybe I will do it that way. Using MSXML just doesn't work when trying to do this.
PS - 15k posts! congrats
-
Re: Indenting XML properly using MSXML4
Try this
VB Code:
Option Explicit
Private oXMLDoc As MSXML2.DOMDocument40
Private mintIndents As Integer
Private Sub Form_Load()
Set oXMLDoc = New DOMDocument40
Me.Show
oXMLDoc.Load "MyXMLFilePath"
RecurseXML oXMLDoc, 0
Set oXMLDoc = Nothing
End Sub
Public Function RecurseXML(ByRef oxmlNode As IXMLDOMNode, Indents As Integer)
Dim oxmlNodeList As IXMLDOMNodeList
Dim lngNodeIndex As Long
Picture1.Print Space(Indents * 4) & oxmlNode.xml
Set oxmlNodeList = oxmlNode.childNodes
If oxmlNode.parentNode Is Nothing Then
Exit Function
End If
If oxmlNode.parentNode.hasChildNodes Then
For lngNodeIndex = 0 To oxmlNodeList.length - 1
mintIndents = mintIndents + 1
RecurseXML oxmlNodeList(lngNodeIndex), mintIndents
mintIndents = mintIndents - 1
Next
Else
Exit Function
End If
End Function
-
Re: Indenting XML properly using MSXML4
Thanks for the code Marty, but that didn't work for the same reason I couldn't get mine to work. It returns something like this:
Code:
<PropertyBag><CProject name="testFileName"><FileName>testFileName</FileName><Title>testTitle</Title><FileCount>1</FileCount><i></i></CProject></PropertyBag>
<CProject name="testFileName"><FileName>testFileName</FileName><Title>testTitle</Title><FileCount>1</FileCount><i></i></CProject>
<FileName>testFileName</FileName>
testFileName
<Title>testTitle</Title>
testTitle
<FileCount>1</FileCount>
1
<i></i>
Theres no way to indent the first and last tags of a parent tag the right way. I think it would have to be done with InStr and Mid and stuff.
I actually threw some XML into an HTML parser I made a while back. It had an extra feature that would autotab the HTML for you, and it works fine for XML as well, but its a TON of code and its very slow, so I would rather start over and make something from scratch than use that.
EDIT: On second thought, maybe I could save that output to a string and use instr() to find all the extra XML at the end of each line. Then I could use the base tag name of the XML to add the </Parent> tags for the parent tags. It might be workable from that code Marty. I'll play with it later.
-
Re: Indenting XML properly using MSXML4
Please attach you XML file.
-
Re: Indenting XML properly using MSXML4
Here it is:
Code:
<PropertyBag><CProject name="testFileName"><FileName>testFileName</FileName><Title>testTitle</Title><FileCount>1</FileCount><i></i></CProject></PropertyBag>
-
Re: Indenting XML properly using MSXML4
Sorry but I can't get it to work on one-line xml files since the .XML property of each node contains all the xml below it.
-
Re: Indenting XML properly using MSXML4
I know. Thats the problem I was having as well. I might try what I mentioned in post #24.
-
Re: Indenting XML properly using MSXML4
Quote:
Originally Posted by eyeRmonkey
higharchial (sp?)
"hierarchial" :)
-
Re: Indenting XML properly using MSXML4
Quote:
Originally Posted by penagate
"hierarchial" :)
:D
I knew that didn't look right.
-
Re: Indenting XML properly using MSXML4
After extensive research I've got the solution! It involves something called an XSL transform.
Here is the code
VB Code:
Option Explicit
Private oXMLDoc As MSXML2.DOMDocument40
Private Sub Form_Load()
Dim oXMLDoc As New DOMDocument40
Dim oXSLT As New DOMDocument40
Dim strResult As String
oXMLDoc.async = False
oXSLT.async = False
oXMLDoc.Load "My.xml"
oXSLT.Load "My.xsl"
strResult = oXMLDoc.transformNode(oXSLT)
oXMLDoc.loadXML strResult
Picture1.Print oXMLDoc.xml
End Sub
And here is the XSL file
Code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
-
Re: Indenting XML properly using MSXML4
I asked this same question a while back on how to indent XML. At the time I need it is because I was dealing with massive XML data. It is much easier to read and edit right there if you have the file open. You can use something like XML Spy to do the edit but sometime it is much quicker to just open a file in Notepad.
I am also like EyeRMonkey where I like it to look right for the reason that when you email the xml file to someone, they might not have XMLSpy.
MartinLiss is on the right path of using recursive functions/subs but takes lots of coding. There are different algorithm of the open tags and close tags.
The fastest way of doing indent for XML file is using VB.Net. I will look for the code and post it. It was just a basic output in .Net.
I also got it to work in VB6 but had to write a several modules of code just to do make it look pretty. You will need to use XPath to find the deepest layer and work your way back out from there.
-
Re: Indenting XML properly using MSXML4
Quote:
Originally Posted by Liquid Metal
I asked this same question a while back on how to indent XML. At the time I need it is because I was dealing with massive XML data. It is much easier to read and edit right there if you have the file open. You can use something like XML Spy to do the edit but sometime it is much quicker to just open a file in Notepad.
I am also like EyeRMonkey where I like it to look right for the reason that when you email the xml file to someone, they might not have XMLSpy.
MartinLiss is on the right path of using recursive functions/subs but takes lots of coding. There are different algorithm of the open tags and close tags.
The fastest way of doing indent for XML file is using VB.Net. I will look for the code and post it. It was just a basic output in .Net.
I also got it to work in VB6 but had to write a several modules of code just to do make it look pretty. You will need to use XPath to find the deepest layer and work your way back out from there.
Check out my latest post above. Recursion isn't necessary!
-
Re: Indenting XML properly using MSXML4
:thumb: You are impressive Martin!
-
Re: Indenting XML properly using MSXML4
Martin, can you explain your xslt file?
Is "xsl:copy" just a tag or is it an actual function of something.
-
Re: Indenting XML properly using MSXML4
Check out this bit of light reading :)
-
1 Attachment(s)
Re: Indenting XML properly using MSXML4
WOW! Many thanks Marty! You clearly put a lot of work into figuring this one out. I really appriciate it.
Okay, I just tested it and I get an error when I try to run the project.
The error says: "The stylesheet does not contain a document element. The stylesheet may be empty, or it may not be a well-formed XML document."
I attachmed my project. Does anyone else get the same error?
-
Re: Indenting XML properly using MSXML4
I ran your project and it ran without errors but the output didn't show up in the picturebox. I then swapped my picturebox for yours and it ran perfectly.
-
Re: Indenting XML properly using MSXML4
Yeah, I was having problems with the picturebox also, thats weird.
I fixed it myself though, I needed to specify the whole path to the XML and XSL files for some reason. No biggy though. After that it worked perfectly. Thanks a million Marty. :D
I think I might package this into a module and post it into the codebank (fully crediting its original author ;)).
-
1 Attachment(s)
Re: Indenting XML properly using MSXML4
Here is your project that works for me. All I did was to change the picturebox.
-
Re: Indenting XML properly using MSXML4
Quote:
Originally Posted by eyeRmonkey
Yeah, I was having problems with the picturebox also, thats weird.
I fixed it myself though, I needed to specify the whole path to the XML and XSL files for some reason. No biggy though. After that it worked perfectly. Thanks a million Marty. :D
I think I might package this into a module and post it into the codebank (fully crediting its original author ;)).
Sure. I was thinking about doing that myself.
-
1 Attachment(s)
Re: Indenting XML properly using MSXML4
How does this look for a CodeBank submission? Should I add real error trapping inside the module? I've never done a real CodeBank sumbission before. Any other suggestions?
-
Re: Indenting XML properly using MSXML4
I don't know why you are hard-coding the xsl file in the program. Why not just open it like I did. I also don't know why you went from MSXML4 to MSXML2.
-
Re: Indenting XML properly using MSXML4
I hard coded it so you can easily add it to any project without having to keep track of the module and the .xsl. I see that as saving time and effort. That way you can just drop in the module to any project that uses XML and you don't have to think about it.
I switched it MSXML2 just in the example project because more people are likely to have MSXML2 than MSXML4 (I just got MSXML4 a few days ago). You can use the module with any version of MSXML.
Does that explain it better? Other than those, are there any changes I should make?
-
1 Attachment(s)
Re: Indenting XML properly using MSXML4
Here is what I'd do. The changes I made were minor and you should feel free to accept or reject any of them. You should of course remove all the commented-out code.
-
1 Attachment(s)
Re: Indenting XML properly using MSXML4
Martin,
I found a situation. Your method of indentation works all fine and dandy when it is just elements and attributes. When there is text in element area, for some reason, it does not indent properly the first element.
I attached a file so you can see the result. Notice, if I take out the text, everything is fine.
-
Re: Indenting XML properly using MSXML4
I forgot to link this thread back to my CodeBank submission. Here is the module that I created after Martin's help in this thread:
http://www.vbforums.com/showthread.php?t=368314
Liquid Metal,
Try that version of the code and see if you get the same results.
-
Re: Indenting XML properly using MSXML4
Still does the same thing. It will indent all except for the first child node under the root if the root has text.
-
Re: Indenting XML properly using MSXML4
I don't know what to say. I feel inclined to blame the MSXML isntead of my/Marty's code because all the code does is apply an XSL transformation and specify that we want to indent. Maybe Marty would have some insight into this problem?
-
Re: Indenting XML properly using MSXML4
Quote:
Originally Posted by eyeRmonkey
I don't know what to say. I feel inclined to blame the MSXML isntead of my/Marty's code because all the code does is apply an XSL transformation and specify that we want to indent. Maybe Marty would have some insight into this problem?
No, sorry, I don't.
-
Re: Indenting XML properly using MSXML4
Thank You Martin and Monkey! It is not a big deal but just thought it was a bit strange. I didn't think it was your/Martin's code but was just puzzle how it were transformed.
-
Re: Indenting XML properly using MSXML4
I'm just curious. Your code reads the XML and formats it properly then prints it into a textbox, but how can i get it to write back to the XML file properly formatted?
-
Re: Indenting XML properly using MSXML4
i aslo do need to indent the xml file created thr' msxml4.0 with vb code not for loos but for finding the location of error om xml validation against xsd.
i do get the eror correctly but its detection in my xml file is difficult as it takes the whole created document as one line document & hence throws the eror no in different columns but samle line , line 1
but techincally on broswwwers it appears orrect , node by node with proper indention
if i redo the xml documnent manually in any ediotr i get the proper location
how do i rectify it thr; code