Microsoft KB Archive/252339

From BetaArchive Wiki
Knowledge Base


How To Acquire Descriptive Information on an XML Error in Visual Basic

Article ID: 252339

Article Last Modified on 6/29/2004



APPLIES TO

  • Microsoft XML Parser 2.0
  • Microsoft XML Core Services 4.0
  • Microsoft XML Core Services 4.0
  • Microsoft ActiveX Data Objects 2.5
  • Microsoft ActiveX Data Objects 2.6
  • Microsoft ActiveX Data Objects 2.7
  • Microsoft Visual Basic 5.0 Professional Edition
  • Microsoft Visual Basic 6.0 Professional Edition
  • Microsoft Visual Basic 5.0 Enterprise Edition
  • Microsoft Visual Basic 6.0 Enterprise Edition



This article was previously published under Q252339

SUMMARY

The XML Object Model provides several ways to handle errors when they occur as a result of the XML document. One of these is the document object's ParseError property, which provides information about problems that may occur in an XML document. This information enables you to handle possible errors and shield users from them. The code sample provided in this article demonstrates the use of some of these properties.

Unicode data is stored as 2 bytes per character, allowing for proper parsing of international language characters and symbols. However, when you save data of this type in ASCII format, errors occur when you try to open and parse the file.

MORE INFORMATION

The following sample utilizes the Customers table in the Microsoft SQL Server Northwind database. Some of the contact names in this table contain international language characters and symbols. The sample creates an ADO recordset by selecting several fields in this table. Subsequently, the data is saved to an XML document using the CreateTextFile method of the FileSystemObject. You can set the last argument of this method to save the file in either Unicode or ASCII format; this argument is optional. If you set the argument to "False" or omit it entirely, the file is created as ASCII.

To see the useful information that can be obtained from the ParseError property, save the data from the Recordset as ASCII. Subsequently, if you try to open the file and parse its data to fill a Visual Basic TreeView control, the error "An Invalid Character Was Found in Text Content" results.
If a newer version of MSXML has been installed in side-by-side mode, you must explicitly use the Globally Unique Identifiers (GUIDs) or ProgIDs for that version to run the sample code. For example, MSXML version 4.0 can only be installed in side-by-side mode. For additional information about the code changes that are required to run the sample code with the MSXML 4.0 parser, click the following article number to view the article in the Microsoft Knowledge Base:

305019 INFO: MSXML 4.0 Specific GUIDs and ProgIds


  1. To run this sample, start a new Visual Basic Standard EXE Project. Form1 is created by default.
  2. From the Project menu, click References, and then select the following items from the References list:

    Microsoft ActiveX Data Objects Library 2.1 or later
    Microsoft XML 1.0 or later
    Microsoft Scripting Runtime*

    • The FileSystemObject Object Model is contained in the Scripting Type Library.

  3. Draw the following controls on Form1 and set their properties as follows:

    Control            Name                    Caption or Text
    
    Command Button     cmdOpenRS               Open A Recordset
    Command Button     cmdSaveRSasXML          Save RS as XML
    Command Button     cmdOpenXMLandDisplay    Open XML File and Display
    Command Button     cmdExit                 Exit
    Text Box           txtErrorInfo            Multi-Line:  True 
                                               ScrollBars:  3-Both
    Label              lblErrorInfo            Error Information:
    TreeView Control*  tvCustErr
                            

    *The TreeView Control is part of the Windows Common Controls.

  4. From the Project menu, select Components, and then click Windows Common Controls.
  5. From the Project menu, select Add Module. Copy the following code into the Module Code Window that appears:

    Option Explicit
    Public cn As New ADODB.Connection
    Public rs As New ADODB.Recordset
    Public myI As Integer
    Public StrTmp As String
    Public Errs1 As Errors
    Public myFSO As New FileSystemObject
    Public mytxtStream As TextStream
    Public domdoc As New MSXML.DOMDocument
    
    ' To specify a specific version, use a declaration like the following, with the appropriate version in the ProgID:
    ' Public domdoc As New MSXML2.DOMDocument40
                        
  6. Copy the following code into the General Declarations section of the code window.

    NOTE: Replace your server name, user ID and password information in the connection string.

    Option Explicit
    
    Private Sub cmdOpenRS_Click()
    
        On Error GoTo AdoError
        
        If cn.State = 1 Then
            cn.Close
            Set cn = Nothing
        End If
        
        If rs.State = 1 Then
            rs.Close
            Set rs = Nothing
        End If
        
        Screen.MousePointer = vbHourglass
        
    '   Change your connections string values here:
        cn.Open "driver={SQL Server};Server=YourServer; " & _
                 "uid=YourUID;pwd=YourPassword;database=Northwind"    
        With rs
            .CursorLocation = adUseClient
            .CursorType = adOpenKeyset
            .LockType = adLockOptimistic
            .CacheSize = 50
            .Source = "Select CustomerID, " & _
            "CompanyName, ContactName, Region from Customers"
            .ActiveConnection = cn
            .Open
        End With
        
        rs.MoveLast
        rs.MoveFirst
        
        Screen.MousePointer = vbNormal
        
        MsgBox "There are " & rs.RecordCount & " Records in the RS"
        
        Exit Sub
    
    AdoError:
    
    Dim errLoop As Error
    Dim strError As String
    
        myI = 1
        
        StrTmp = StrTmp & vbCrLf & "VB Error # " & Str(Err.Number)
        StrTmp = StrTmp & vbCrLf & "   Generated by " & Err.Source
        StrTmp = StrTmp & vbCrLf & "   Description  " & Err.Description
        
    ' Display Error Information for each Error object.
        Set Errs1 = cn.Errors
        For Each errLoop In Errs1
            With errLoop
                StrTmp = StrTmp & vbCrLf & "Error #" & myI & ":"
                StrTmp = StrTmp & vbCrLf & "   ADO Error   #" & .Number
                StrTmp = StrTmp & vbCrLf & "   Description  " & .Description
                StrTmp = StrTmp & vbCrLf & "   Source       " & .Source
                myI = myI + 1
            End With
        Next
        
        MsgBox StrTmp
    
    End Sub
    
    Private Sub cmdExit_Click()
    
        If cn.State = 1 Then
            cn.Close
            Set cn = Nothing
        End If
        
        If rs.State = 1 Then
            rs.Close
            Set rs = Nothing
        End If
        
        Unload Me
    
    End Sub
    
    Private Sub cmdOpenXMLandDisplay_Click()
    
    On Error GoTo MyXMLPerr
    
    'Fill The TreeView with data from the XML Document:
    
        With domdoc
            .async = False
            .Load App.Path & "\CustErr.xml"
        End With
    
        If domdoc.readyState = 4 Then
            tvCustErr.Nodes.Clear
            AddNode domdoc.documentElement
        End If
        
        Exit Sub
        
    'If an error occurs, display the Source of the error, the line number
    'in the XML Document that the error occurred on and the text of the error:
    
    MyXMLPerr:
    
           txtErrorInfo.Text = domdoc.parseError.reason & vbCrLf & _
                                " Line Number In Document: " & domdoc.parseError.Line & _
                                vbCrLf & domdoc.parseError.srcText
    
    End Sub
    
    Private Sub cmdSaveRSasXML_Click()
    
       Screen.MousePointer = vbHourglass
    
    'If the file already exists, first Kill it
    'and then create it.
    'If it does not already exist, simply create it:
       On Error GoTo mdkNoSeeEm
       Const mdkNoSeeEm = 53 'File Not Found
       Kill "Customers.xml"
    
    'Create a Text file using the FileSystemObject:
    'For Ascii, last setting is False.  Unicode is True
    
       Set mytxtStream = myFSO.CreateTextFile(App.Path & "\CustErr.xml", True, False)
       
    'To save the file in Unicode format
        'Set mytxtStream = myFSO.CreateTextFile(App.Path & "\CustErr.xml", True, True)
    
       mytxtStream.WriteLine "<?xml version=""1.0"" standalone=""yes""?>"
       mytxtStream.WriteLine "<Customers>"
    
       rs.MoveFirst
    
       Do While Not rs.EOF
            mytxtStream.WriteLine "<Customer>"
            mytxtStream.WriteLine "<CustomerID>" & _
                                    rs.Fields("CustomerID") & "</CustomerID>"
            mytxtStream.WriteLine "<CompanyName>" & _
                                    rs.Fields("CompanyName") & "</CompanyName>"
            mytxtStream.WriteLine "<ContactName>" & _
                                    rs.Fields("ContactName") & "</ContactName>"
            mytxtStream.WriteLine "<Region>" & rs.Fields("Region") & "</Region>"
            mytxtStream.WriteLine "</Customer>"
            rs.MoveNext
       Loop
       rs.MoveFirst
    
       mytxtStream.WriteLine "</Customers>"
    
       mytxtStream.Close
    
       Screen.MousePointer = vbNormal
    
       Exit Sub
    
    mdkNoSeeEm:
        If Err.Number = mdkNoSeeEm Then
            Resume Next
        End If
           
        Screen.MousePointer = vbNormal
    
    End Sub
    
    Private Sub AddNode(ByRef myNode As IXMLDOMNode, Optional ByRef TreeNode As Node)
    
    Dim tvcusterrNode As Node
    Dim tvcusterrNodeList As IXMLDOMNodeList
    Dim i As Long
              
        If TreeNode Is Nothing Then
            Set tvcusterrNode = tvCustErr.Nodes.Add
        Else
            Set tvcusterrNode = tvCustErr.Nodes.Add(TreeNode, tvwChild)
        End If
        
        tvcusterrNode.Expanded = True
        tvcusterrNode.Text = myNode.nodeName
        
        If tvcusterrNode.Text = "#text" Then
            tvcusterrNode.Text = myNode.nodeTypedValue
        Else
            tvcusterrNode.Text = "<" & tvcusterrNode.Text & ">"
        End If
    
        Set tvcusterrNodeList = myNode.childNodes
        For i = 0 To tvcusterrNodeList.length - 1
            AddNode tvcusterrNodeList.Item(i), tvcusterrNode
        Next
    End Sub
  7. Run the project.
  8. Click the Open A Recordset command button to open a connection and recordset, which displays the RecordCount property.
  9. Click Save RS as XML to create the XML document file. Note that the last argument of the CreateTextFile is initially set to "False" in order to create the file in ASCII format.
  10. Click Open XML File and Display. If an error occurs, the error information will be displayed in the Error Information text box.
  11. In this scenario, the details on the reason, line, and source text for the error are displayed as follows:
    An Invalid character was found in text content.
    Line Number In Document: 17
    <CompanyName>Antonio Moreno Taquer?/CompanyName>
                                
    This message indicates that there is an invalid character in the CompanyName element on line 17 of the XML document. To view the actual data on line 17 of the document object model, open the file with a text editor that is capable of numbering the lines, such as Microsoft Excel. This will show that the actual company name of the data on line 17 contains a special character above the "i" in "Taqueria."
  12. To avoid this error, go into the code window for the Save RS as XML command button (cmdSaveRSasXM). Comment out the line that creates the file with its last argument set to "False".
  13. Uncomment the line that creates the file with its last argument set to "True".
  14. Run the project again. The error described in this article will not occur.

Note, however, that other errors may occur. For example, the error indicating that "White Space is Not Allowed" might occur. This likely indicates that special characters (such as brackets, ampersands, apostrophes, or double quotation marks) exist in the document. XML predefines entity references or escape characters for these.

REFERENCES

For additional information regarding the handling of these characters, click the article number below to view the article in the Microsoft Knowledge Base:

251354 How To Locate and Replace Special Characters in an XML Document with Visual Basic


Keywords: kbhowto kbdatabase KB252339