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.
|
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
|