Google Answers Logo
View Question
 
Q: XML in VB6 ( Answered 5 out of 5 stars,   1 Comment )
Question  
Subject: XML in VB6
Category: Computers > Programming
Asked by: ny_insomniac-ga
List Price: $10.00
Posted: 13 Mar 2003 07:40 PST
Expires: 12 Apr 2003 08:40 PDT
Question ID: 175630
Can you provide a quick code sample of how to read from and write to
an xml file using Visual Basic 6?

Request for Question Clarification by googleexpert-ga on 13 Mar 2003 08:09 PST
Have you checked out this page?
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbcon/html/vbwlkwalkthroughaccessingxmldata.asp

Clarification of Question by ny_insomniac-ga on 13 Mar 2003 10:24 PST
The page is helpful, but I'm looking for something in VB6 (not
VB.net), and without a data grid.  Just some simple code that will
allow me to create an XML file and add some text under a tag, and open
an XML file and read a data element.  I can figure out the rest from
there.

Request for Question Clarification by mathtalk-ga on 13 Mar 2003 23:10 PST
Are you wanting to use the MSXML parser (a COM component)?  Or to do
this by brute force?

Context: Last year I wrote a simple VB6 application that opens an XML
file, applies an XSLT transformation, and saves the result (which
might be XML or text output) to a file.  It uses two MSXML objects,
one for the input XML file and one for the XSLT document.

regards, mathtalk

Clarification of Question by ny_insomniac-ga on 14 Mar 2003 08:15 PST
Yes, I want to use the MSXML parser (is that msxml3.dll?), or any
other dll or component that is normally used.
Answer  
Subject: Re: XML in VB6
Answered By: mathtalk-ga on 14 Mar 2003 10:57 PST
Rated:5 out of 5 stars
 
Hi, ny_insomniac-ga:

The current version of Microsoft's XML parser is MSXML 4.0
(implemented in MSXML4.DLL), which provides a number of XML related
API's:

- the Document Object Model (DOM)

- the XML Schema Definition language (XSD)

- the Schema Object Model (SOM)

- Extensible Stylesheet Language Transformations (XSLT)

- the XML Path language (XPath)

- the Simple API for XML (SAX)

[MSXML 4.0 SDK]
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/xmlsdk/htm/sdk_intro_6g53.asp

This version is a replacement for the 3.0 parser (which was
implemented as you say by MSXML3.DLL), but you don't need to upgrade
just to use the code snippet below.  It was orginally written to use
MSXML 3.0.  [Microsoft did some wacky stuff with allowing the 3.0
parser to be installed either as a replacement for the 2.0 parser or
in "side by side" mode.  Apparently the complications were bad enough
that the new parser installs only in "replace" mode.]

In order to use the MSXML parser in your VB6 project, you'll have to
add a reference to the project for this library:

Microsoft XML, v3.0

or alternatively:

Microsoft XML, v4.0

In addition, to use my coding approach you'll want to add a reference
to the Microsoft Scripting Runtime (SCRRUN.DLL in the Windows\System
directory) since that is a easy way to get text stream support in VB6.
 The list of References for your project can be viewed/edited from the
Project > References... dialog in the IDE.  The "available references"
which are checked in my project are as follows:

Visual Basic for Applications
Visual Basic runtime objects and procedures
Visual Basic objects and procedures
OLE Automation
Microsoft XML, v3.0
Microsoft Scripting Runtime

My simple XML "testbench" program in VB6 uses textbox controls
(Text1,Text2 for the input file names, Text3 for the output file name)
and a couple of buttons to apply the XSLT transform (one for XML
output, one for text output).  The output methods differ.  For an XML
result I call transformNodeToObject and that creates a third DOM
object (xmlOut), upon which I use the Save method.  For a text string
result I call use transformNode and pass the resulting expression as
an argument to the Write method of a text stream for output.

The "interesting" code is the event handling behind the click events
for those two buttons.  For the sake of completeness I'll present the
full routine for both.  Here's the version that produces XML output:

Dim strInXML As String
Dim strXSLT As String
Dim strOutput As String

Dim fso As New FileSystemObject
Dim fil As File
Dim ts As TextStream

Dim rslt As Boolean

If fso.FileExists(Text1.Text) Then
    Set fil = fso.GetFile(Text1.Text)
    Set ts = fil.OpenAsTextStream(ForReading)
    strInXML = ts.ReadAll
    ts.Close
Else
    MsgBox ("Input XML File Doesn't Exist")
    Exit Sub
End If

Dim xmlDoc As New MSXML2.DOMDocument
rslt = xmlDoc.loadXML(strInXML)

If Not rslt Then
    MsgBox ("Input XML File Doesn't Parse")
    Exit Sub
End If

If fso.FileExists(Text2.Text) Then
    Set fil = fso.GetFile(Text2.Text)
    Set ts = fil.OpenAsTextStream(ForReading)
    strXSLT = ts.ReadAll
    ts.Close
Else
    MsgBox ("XSLT File Doesn't Exist")
    Exit Sub
End If

Dim xslDoc As New MSXML2.DOMDocument
rslt = xslDoc.loadXML(strXSLT)

If Not rslt Then
    MsgBox ("XSLT File Doesn't Parse")
    Exit Sub
End If

' now we have both the XML and XSLT documents
Dim xmlOut As New MSXML2.DOMDocument
xmlDoc.transformNodeToObject xslDoc, xmlOut
xmlOut.save Text3.Text

Set xmlOut = Nothing
Set xmlDoc = Nothing
Set xslDoc = Nothing

When I banged this together, I couldn't see a simple way to combine
the cases of XML output and text output, so I just made a separate
button for each case (assume an intelligent user, ummmm... or me). 
Here's the text output handler, which differs in creating a text
stream for output:

Dim strInXML As String
Dim strXSLT As String
Dim strOutput As String

Dim fso As New FileSystemObject
Dim fil As File
Dim ts As TextStream

Dim rslt As Boolean

If fso.FileExists(Text1.Text) Then
    Set fil = fso.GetFile(Text1.Text)
    Set ts = fil.OpenAsTextStream(ForReading)
    strInXML = ts.ReadAll
    ts.Close
Else
    MsgBox ("Input XML File Doesn't Exist")
    Exit Sub
End If

Dim xmlDoc As New MSXML2.DOMDocument
rslt = xmlDoc.loadXML(strInXML)

If Not rslt Then
    MsgBox ("Input XML File Doesn't Parse")
    Exit Sub
End If

If fso.FileExists(Text2.Text) Then
    Set fil = fso.GetFile(Text2.Text)
    Set ts = fil.OpenAsTextStream(ForReading)
    strXSLT = ts.ReadAll
    ts.Close
Else
    MsgBox ("XSLT File Doesn't Exist")
    Exit Sub
End If

Dim xslDoc As New MSXML2.DOMDocument
rslt = xslDoc.loadXML(strXSLT)

If Not rslt Then
    MsgBox ("XSLT File Doesn't Parse")
    Exit Sub
End If

' now we have both the XML and XSLT documents

Set ts = fso.CreateTextFile(Text3.Text, True, False)
ts.Write (xmlDoc.transformNode(xslDoc))
ts.Close

Set xmlOut = Nothing
Set xmlDoc = Nothing
Set xslDoc = Nothing

regards, mathtalk-ga


Search Strategy

visited MSDN Online, my homepage, to snag the XML SDK link
fired up VB6 & SourceSafe on my Win98 laptop

Request for Answer Clarification by ny_insomniac-ga on 20 Mar 2003 06:01 PST
I was able to open an XML document, find a node, and read the full xml
on a node.  But how do I read a specific element (i.e. 'lastName' from
a Node).  Can you please add the last line of code to the example
below:

Dim oxmldom As DOMDocument30
Dim oNodes As IXMLDOMNodeList
Dim oNode As IXMLDOMNode

Set oxmldom AS New DOMDocument30
oxmldom.Load "c:\resources.xml"
Set oNodes = oxmldom.getElementsByTagName("Resource")
    
Set oNode=oNodes.Item(0)
msgbox onode.xml
'Add line to read 'lastName' element from Resource Node

Clarification of Answer by mathtalk-ga on 20 Mar 2003 10:49 PST
Hi,ny_insomniac-ga:

With XML generally and with the DOM interfaces in particular, there
are always several ways to do the same thing.  I'll pick one that at
least exposes some important functionality involving XPath expressions
through a Microsoft 'extension' of the W3C Document Object Model
standard.

In your code you have 'navigated' from the entire document down to the
first of a list of nodes whose tag names are "Resource".

Picking up the story from there, you have stored a single node in the
object variable oNode, which as an XML node may itself have children.

A very flexible method which can be used with such a document node
(any object which implements IXMLDOMNode) is selectSingleNode, a
method which takes an XPath select expression as its argument.

If what you seek is an immediate child element with tag name
"lastname" in the context defined by oNode, then the syntax would be:

oNode.setProperty "SelectionLanguage", "XPath"
' included only for MSXML 3.0 compatibility (see below)

Dim oChild As IXMLDOMNode
Set oChild = oNode.selectSingleNode("lastname")

You could then display the text or xml property of the resulting node
oChild.

When the element whose tag name is "lastname" is buried more deeply in
the context, things get more complicated.  If the exact manner in
which the elements of oNode are nested is unknown, then one can use
the 'recursive' operator // to indicate that the entire hierarchy
below oNode is to be searched:

Set oChild = oNode.selectSingleNode("//lastname")

For the syntax of the selectSingleNode method as it applies to
document nodes and a few other interfaces, see here:

[selectSingleNode Method]
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/xmlsdk30/htm/xmmthselectsinglenode.asp

For more information on the syntax of XPath select expressions,
consult the XML SDK documentation or see here:

[XPath Examples]
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/xmlsdk/htm/xpath_syntax2_3prn.asp

XPath is one of the "enabling" standards for XML parsing defined here:

[W3C: XPath]
http://www.w3.org/TR/xpath

The SelectionLanguage property of document nodes and objects in MSXML
4.0 is always "XPath".  In MSXML 3.0 it was necessary to explicitly
set the internal flag to "XPath" because the default value was
"XSLPattern", invoking an earlier Microsoft proposed construct.  Only
XPath is supported in MSXML 4.0, so this property can be ignored,
although it exists as a property for the sake of compatibility with
existing code:

[SelectionLanguage Property]
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/xmlsdk/htm/xml2nd_pro_v4_9rc5.asp

regards, mathtalk

Request for Answer Clarification by ny_insomniac-ga on 20 Mar 2003 14:23 PST
Sorry for the persistence.  I promise this is the last clarification
for the 5th star.

My xml file is formatted like this:
<Resource lastName="Jones" firstName="Steve">
<Resource lastName="Smith" firstName="John">

When I ask for the SelectSingleNode for 'lastName' or if I ask for
child nodes under 'Resource', I get nothing back.  Is there a special
way of reading the attributes within the element?

Clarification of Answer by mathtalk-ga on 20 Mar 2003 22:08 PST
Hi, ny_insomniac-ga:

Okay, I see what is going on.  Those sorts of data items are not
elements but attributes.

Both elements and attributes are considered "nodes", but they are two
different kinds of nodes.  In fact elements and attributes are the two
most common node types (there are a dozen different node types in all,
including things like comments, processing instructions, and
entities).  Elements have tag names, and optionally they can have
attributes, text content, and child elements.  Attributes have
attribute names, and optionally they can have a value/text content,
but no nested 'children' of any kind.

Microsoft implements the DOM using COM interfaces, and both
IXMLDOMElement and IXMLDOMAttribute 'inherit' from IXMLDOMNode as a
way of representing that elements and attributes are similar yet
distinct kinds of nodes.

An XPath expression which selects an attribute of the current context
named "lastName" is simply this:

@lastName

So in principle, once oNode has been assigned to a "Resource" element
node, we should be able to do something like this:

Dim oAttrib As IXMLDOMNode
Set oAttrib = oNode.selectSingleNode("@lastName")

and then display the attribute's value with:

MsgBox oAttrib.xml

But let's back up.  I don't think I'd use selectSingleNode to pull out
an attribute value.  selectSingleNode is attractive for finding
element nodes because it brings the 'search' capabilities of XPath to
bear on possibly complex problems of navigating the element hierarchy.

However with attributes, there is no nesting and no complex hierarchy
to navigate.  I think I'd go with a different approach, like this:

Dim oxmldom As DOMDocument30 
Set oxmldom = New DOMDocument30 
oxmldom.async = False
oxmldom.Load "c:\resources.xml" 
oxmldom.setProperty "SelectionLanguage", "XPath"

Dim oElement As IXMLDOMElement
Set oElement = oxmldoc.selectSingleNode("//Resource")
Dim oAttrib As IXMLDOMAttribute
Set oAttrib = oElement.getAttributeNode("lastName")
MsgBox oAttrib.Text

To test both approaches, I created an XML file, resources.xml, in the
root of my C: drive, like this:

<?xml version="1.0"?> 
<Project>
  <Resource lastName="Jones" firstName="Steve" /> 
  <Resource lastName="Smith" firstName="John" /> 
</Project>

Then I wrote a quick VB6 program with the above code assigned to the
Click Event for a big Command button I placed in the middle of an
otherwise empty form.

Both approaches work fine.  However the first approach, using
oAttrib.xml, displays the string:

lastName="Jones"

where the second approach, using oAttrib.Text, displays just the value
Jones.  Of course one can use either output expression with either
'navigational' technique.

regards, mathtalk-ga
ny_insomniac-ga rated this answer:5 out of 5 stars
It works!  Microsoft made it fun for us with a difference between
Nodes, Elements, and Attributes, but you got me through it.  Thanks.

Comments  
Subject: Re: XML in VB6
From: xandergiles-ga on 13 Mar 2003 12:09 PST
 
This discussion demonstrates how you can add persistance to a simple
class called in your application. First, assume the class is called
cName and has the following definition:

   Option Explicit

   Private m_sFirstName As String
   Private m_sLastName As String

   Public Property Get FirstName() As String
      FirstName = m_sFirstName
   End Property
   Public Property Let FirstName(ByVal sName As String)
      m_sFirstName = sName
   End Property

   Public Property Get LastName() As String
      FirstName = m_sFirstName
   End Property
   Public Property Let LastName(ByVal sName As String)
      m_sLastName = sName
   End Property

The first step is to implement the IXMLPropertyBag interface. Add this
code to the class:

   Implements IXMLPropertyBag

      ...

   Private Sub IXMLPropertyBag_ReadProperties(ByVal PropertyBag As
vbalXMLPBag.XMLPropertyBag)
   '
   End Sub

   Private Sub IXMLPropertyBag_WriteProperties(ByVal PropertyBag As
vbalXMLPBag.XMLPropertyBag)
   '
   End Sub

Now you can fill in your ReadProperties and WriteProperties
implementations:

   Private Sub IXMLPropertyBag_ReadProperties(ByVal PropertyBag As
vbalXMLPBag.XMLPropertyBag)
      '
      FirstName = PropertyBag.ReadProperty("FirstName", "")
      LastName = PropertyBag.ReadProperty("LastName", "")

   End Sub

   Private Sub IXMLPropertyBag_WriteProperties(ByVal PropertyBag As
vbalXMLPBag.XMLPropertyBag)
      '
      PropertyBag.WriteProperty "FirstName", FirstName, ""
      PropertyBag.WriteProperty "LastName", LastName, ""

   End Sub

Once that is done, you can now save and restore cName objects at will.
For example, this code:

   Private m_cN As New cName

   Public Function SaveName() As String

      ' Create an instance of the XML Property bag object:
      Dim oP As New XMLPropertyBag

      ' Save cName into the property bag:
      oP.SaveState m_cN

      ' Now the content is saved in the return value:
      SaveName = oP.Contents

   End Sub

   Public Sub RestoreName(ByVal sXML As String)

      ' Create an instance of the XML Property bag object:
      Dim oP As New XMLPropertyBag

      ' Load the XML into it:
      oP.Contents = sXML

      ' Restore the object:
      oP.RestoreState m_cN

   End Sub

Important Disclaimer: Answers and comments provided on Google Answers are general information, and are not intended to substitute for informed professional medical, psychiatric, psychological, tax, legal, investment, accounting, or other professional advice. Google does not endorse, and expressly disclaims liability for any product, manufacturer, distributor, service or service provider mentioned or any opinion expressed in answers or comments. Please read carefully the Google Answers Terms of Service.

If you feel that you have found inappropriate content, please let us know by emailing us at answers-support@google.com with the question ID listed above. Thank you.
Search Google Answers for
Google Answers  


Google Home - Answers FAQ - Terms of Service - Privacy Policy