Results 1 to 18 of 18

Thread: VB6 & MSXML4 Issues

  1. #1

    Thread Starter
    New Member
    Join Date
    Jan 2010
    Posts
    15

    VB6 & MSXML4 Issues

    Using VB6 (not my decision) and MSXML4, I'm trying to create and send an XML file to a web services call (exe) that transmits the XML as inputs to another application and returns another XML as outputs. I'm having trouble in the following areas:

    * Creating attributes for certain elements. It seems like I can only do it on the root.

    * Referencing the web services call application (*.exe) in VB6 & then sending it the XML input file as an argument.

    * Validating an XML input file against a *.xsd schema

    If there's an easy way to bring up a template XML file (schema?) and then populate it as needed, I'd like to know how. That would make my life a lot easier. Right now I'm trying to create the XML input files from scratch.

    The only book resource I've found that handles VB6/XML is XML Programming with VB and ASP by Mark & Tracey Wilson (2000). I've had trouble taking sample code from web and getting it to work properly. Any guidance would be appreciated. Thank you!

  2. #2

    Thread Starter
    New Member
    Join Date
    Jan 2010
    Posts
    15

    VB6 & MSXML4: Issue Adding Attributes

    I'm having trouble populating attributes in the code below. It works for the root but not the child level. I've tried various ways but can't get it to work. Please help me if you can. Thanks!

    Private Sub cmdTestVBF_Click()

    Dim oRoot As IXMLDOMElement
    Dim oLevel1 As IXMLDOMElement
    Dim oLevel2 As IXMLDOMElement
    Dim oNode As IXMLDOMNode

    XMLOUTPATH = App.Path & "\XmlOuput_TestVBF.xml"

    Set oDoc = New DOMDocument
    oDoc.resolveExternals = True

    Set oRoot = oDoc.createElement("Parent")
    Set oDoc.documentElement = oRoot
    oRoot.setAttribute "xmlns", "http://blah/blah/blah"
    oRoot.setAttribute "xmlns:i", "http://www.w3.org/2001/XMLSchema-instance"

    Set oNode = oDoc.createElement("Child1")
    oNode.Text = "2010-03-08T00:00:00"
    oRoot.appendChild oNode

    Set oLevel1 = oDoc.createElement("Child2")
    oRoot.appendChild oLevel1

    Set oLevel2 = oDoc.createElement("Grandchild")
    'Want entry to look like: <Grandchild i:type="abc">
    oLevel1.appendChild oLevel2

    Set oNode = oDoc.createElement("GreatGrandchild")
    oNode.Text = "Adding text works fine"
    oLevel2.appendChild oNode

    Set oNode = oDoc.createElement("Child3")
    oNode.Text = "Adding text works fine"
    oRoot.appendChild oNode

    Set oNode = oDoc.createElement("Child4")
    'Want entry to look like: <Child4 i:nil="true" />
    oRoot.appendChild oNode

    ' Save xml file
    oDoc.save XMLOUTPATH

    MsgBox XMLOUTPATH & " is created for you."

    End Sub

    DESIRED OUTPUT (spacing not shown correctly in this post but code generates properly spaced XML file. I just need help on how to populate attributes.)

    - <Parent xmlns="http://blah/blah/blah" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <Child1>2010-03-08T00:00:00</Child1>
    - <Child2>
    - <Grandchild i:type="abc">
    <GreatGrandchild>Adding text OK</GreatGrandchild>
    </Grandchild>
    </Child2>
    <Child3>Adding text OK</Child3>
    <Child4 i:nil="true" />
    </Parent>

  3. #3
    Former Admin/Moderator MartinLiss's Avatar
    Join Date
    Sep 1999
    Location
    San Jose, CA
    Posts
    33,431

    Re: VB6 & MSXML4 Issues

    Code:
    Public Function AddAttribute(oDOM As DOMDocument, _
                                oElement As IXMLDOMElement, _
                                sName As String, _
                                sValue As String, _
                                Optional bReplace As Boolean = False _
                                ) As Boolean
        On Error GoTo ErrHand
        
        Dim oAttr As IXMLDOMAttribute
        Dim bResults As Boolean
        
        ' First see if the attribute already exists ...
        If (Not oElement.Attributes.getNamedItem(sName) Is Nothing) Then
            If bReplace = False Then
                bResults = False
            End If
        Else
            Set oAttr = oDOM.createAttribute(sName)
            oElement.setAttribute sName, sValue
            bResults = True
        End If
        
    ErrHand:
    
        Set oAttr = Nothing
        
        If Err.Number <> 0 Then
            Call SetErrorInfo(Err.Number, Err.Description, "CDomFunctions." & Err.Source, UNKNOWN)
            bResults = False
        End If
        
        AddAttribute = bResults
    End Function

  4. #4

  5. #5

  6. #6

    Thread Starter
    New Member
    Join Date
    Jan 2010
    Posts
    15

    Re: VB6 & MSXML4 Issues

    Thanks, Marty! The code you supplied for adding attributes worked. I will look into the link for validation against schema. Sorry about posting overlapping postings. I posted the second one after realizing I didn't provide enough detail in the first one.

    Here's some more detail regarding my original post above regarding "Referencing the web services call application (*.exe) in VB6 & then sending it the XML input file as an argument.":

    Once I have the XML file similar to the one created above, then I need to send it to a web services client app (webservicecall.exe). This application takes my XML input file and generates an output XML file. I'm having trouble calling the application with the required arguments in VB6. The following code works from the DOS prompt, assuming the test_input_VB6.xlm is created:

    C:\ABC\123\WebserviceClient\WebserviceCall\>webservicecall.exe /trade http://wdorm102w:8086 c:\input\test_input_VB6.xml
    c:\output\test_output.xml 89_Client

    Do you know how I should set up this call in VB6? Finally, what's the easiest way to reference one NodeTypedValue of the XML output file? Any further help would be greatly appreciated. Thanks again!

  7. #7

  8. #8

    Thread Starter
    New Member
    Join Date
    Jan 2010
    Posts
    15

    Re: VB6 & MSXML4 Issues

    My application call from within VB6 just happens to be for web services, but I'm pretty sure the syntax would be the same regardless. So if you're familiar with making external calls to exe files from within VB6, your words of wisdom would help. Otherwise, I'll wait for someone else to respond and I'll continue tinkering with it. Also, I'll search more in the forum. Thanks!

  9. #9

  10. #10
    PowerPoster dilettante's Avatar
    Join Date
    Feb 2006
    Posts
    24,487

    Re: VB6 & MSXML4 Issues

    There is almost nothing to be gained by going through a DOM to create a file containing XML. Just write the XML text to a file. If you need a particular encoding like UTF-8 you can use an ADODB.Stream object to handle the conversion from internal Unicode to another encoding, use LF as line-ends as needed, etc.

    An XSD is almost useless for creating an XML document. The main purpose of XSD is:
    • To serve as particularly clunky documentation for programmers creating an XML document.
    • For automated validation of XML documents produced by another program.

    You can't feed XSD to a DOM object and get an XML document. The XSD is at best a template for a highly variable structure. Many nodes defined in XSD can be optional or occur some variable number of times, and this is also true of sub-nodes.

    You can't "call" an EXE, but you can run it. I see no advantage to calling ShellExecute to accomplish this. Just use VB's intrinsic Shell function. Shell will return a task ID for the child process, which can be converted to a process handle you can use to wait for the child to complete. Get the process handle by calling OpenProcess. If you require greater functionality you'll have to call CreateProcess yourself, which is what both Shell and ShellExecute do for you (after making a number of assumptions).

    A search here should turn up multiple examples of "shell and wait" code.

  11. #11

    Thread Starter
    New Member
    Join Date
    Jan 2010
    Posts
    15

    Re: VB6 & MSXML4 Issues

    Thanks, dilettante! I found a snippet of "shell and wait" code that works for my situation. It generates the desired XML output file. Now I only need to read one value from an element returned in that XML output file. Is there a simple way to extract this value? (I haven't programmed much in VB6 since the late 1990's, and I'm struggling to get back in the swing of things, especially with XML.) Any help would be appreciated!

  12. #12
    PowerPoster dilettante's Avatar
    Join Date
    Feb 2006
    Posts
    24,487

    Re: VB6 & MSXML4 Issues

    If you only need one a couple of Split()s should do it.

  13. #13

    Thread Starter
    New Member
    Join Date
    Jan 2010
    Posts
    15

    Re: VB6 & MSXML4 Issues

    I didn't see anything out there related to Splits. Basically, I'm having trouble finding code to do a very simple task, which is to load an XML file and read one or more values from certain nodes. For example, if I had the xml file below, what would I need to do to open and read the values of 100 and 200 from the GreatGrandchild nodes? Does it matter that the nodes are called the same thing if there's some other way to distinguish them (abc, def, etc.)?

    - <Parent xmlns="http://blah/blah/blah" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <Child1>2010-03-08T00:00:00</Child1>
    - <Child2>
    - <Grandchild i:type="abc">
    <GreatGrandchild>100</GreatGrandchild>
    </Grandchild>
    </Child2>
    - <Child2>
    - <Grandchild i:type="def">
    <GreatGrandchild>200</GreatGrandchild>
    </Grandchild>
    </Child2>
    <Child3>Adding text works fine</Child3>
    <Child4 i:nil="true" />
    </Parent>

  14. #14
    PowerPoster dilettante's Avatar
    Join Date
    Feb 2006
    Posts
    24,487

    Re: VB6 & MSXML4 Issues

    Keep in mind this is very simple-minded. It makes a number of assumptions:
    • You only need the GreatGrandchild text (values).
    • Tags don't have erratic whitespace in them, and GreatGrandchild tags have no attributes.

    Code:
    Sub ParseCountDisplay()
        Dim intXMLFile As Integer
        Dim strXML As String
        Dim strXMLParts() As String
        Dim strGGCParts() As String
        Dim intXMLPart As Integer
        Dim intGGCCount As Integer
        
        intXMLFile = FreeFile(0)
        Open "GreatGrandchild.xml" For Input As #intXMLFile
        strXML = Input$(LOF(intXMLFile), intXMLFile)
        Close #intXMLFile
        
        strXMLParts = Split(strXML, "<GreatGrandchild>", , vbTextCompare)
        'Skip 0th entry, no data there:
        For intXMLPart = 1 To UBound(strXMLParts)
            strGGCParts = Split(strXMLParts(intXMLPart), _
                                "</GreatGrandchild>", _
                                , _
                                vbTextCompare)
            If UBound(strGGCParts) = 1 Then
                'Found a good GreatGrandchild.
                txtLog.Text = txtLog.Text & strGGCParts(0) & vbNewLine
                intGGCCount = intGGCCount + 1
            End If
        Next
        txtLog.Text = txtLog.Text & vbNewLine _
                    & "Count = " & CStr(intGGCCount) & vbNewLine
        Caption = Caption & " (Done)"
    End Sub
    Both of those assumptions may by acceptable to you, or not. If not, you can write more sophisticated parsing logic, probably based on InStr() instead of Split().

    However if your requirements get much more sophisticated you can always use MSXML. You can do this either using SAX directly, or by using a DOM and letting it invoke SAX internally to parse the document into a DOM tree.

    My offhand guess would be that your XML documents are well under 50KB and performance is not critical. This means the extra coding needed to use the SAX parser in MSXML yourself isn't worthwhile. Your average Joe typically just slops it into a DOM and traverses the resulting node tree, with no ill impact.


    If your needs are really simple though, very simple parsing techniques can be used to extract nominal amounts of information without using MSXML at all.
    Attached Files Attached Files

  15. #15

    Thread Starter
    New Member
    Join Date
    Jan 2010
    Posts
    15

    Re: VB6 & MSXML4 Issues

    Thanks again, dilettante!
    Last edited by DMVA; Mar 12th, 2010 at 12:04 PM.

  16. #16

    Thread Starter
    New Member
    Join Date
    Jan 2010
    Posts
    15

    Re: VB6 & MSXML4 Issues

    Using the original code posted in the thread, how would I add the following line at the beginning of the XML file:

    <?xml version="1.0" encoding="UTF-8" standalone="no" ?>

    I've tried various things and searched this forum, but I can't find anything that works. Please let me know if you can help. Thanks!

  17. #17
    Former Admin/Moderator MartinLiss's Avatar
    Join Date
    Sep 1999
    Location
    San Jose, CA
    Posts
    33,431

    Re: VB6 & MSXML4 Issues

    When you have a new question you are better off starting a new thread but...

    xmldoc.createProcessingInstruction("xml"," version='1.0' encoding=UTF-8 standalone=no")

    I'm not sure single or double quote requirements for the standalone part.

  18. #18
    PowerPoster dilettante's Avatar
    Join Date
    Feb 2006
    Posts
    24,487

    Re: VB6 & MSXML4 Issues

    This can get a little complicated. If you want UTF-8 you can't just use the DOM's .xml property because it always converts to UTF-16LE/UCS-2. It has to, because it returns a String and a String is always UTF-16.

    Note the differences in results from the two MsgBox popups (modified example from MSDN Library):
    Code:
        Dim xmlDoc As New MSXML2.DOMDocument40
        Const attribs As String = _
            "version=""1.0"" encoding=""UTF-8"" standalone=""no"""
        Dim pi As IXMLDOMProcessingInstruction
        Dim stm As New ADODB.Stream
        
        xmlDoc.async = False
        xmlDoc.loadXML "<root><child/></root>"
        If xmlDoc.parseError.errorCode <> 0 Then
            MsgBox xmlDoc.parseError.reason, , "Parse error"
        Else
            Set pi = xmlDoc.createProcessingInstruction("xml", attribs)
            xmlDoc.insertBefore pi, xmlDoc.childNodes.Item(0)
            MsgBox xmlDoc.xml, , "String property .xml"
            With stm
                .Open
                xmlDoc.save stm
                .Position = 0
                .Type = adTypeText
                .Charset = "utf-8"
                MsgBox .ReadText(adReadAll), , "Method .save output converted to UTF-16"
                .Close
            End With
        End If
    First:
    Code:
    <?xml version="1.0" standalone="no"?>
    <root><child/></root>
    Second:
    Code:
    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <root><child/></root>
    The second result is not UTF-8. It shows the UTF-8 output from the xmlDoc.save after converting it from UTF-8 to "Unicode" (UTF-16LE) using an ADODB.Stream object.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width