k_Dank
k_Dank

Reputation: 695

Using Sax parsing to edit and write XML in VB6

So I am trying to edit an xml (output is an xml) using SAX parsing in VB6 (for an ancient COM component). I would prefer to use DOM parsing but the size of the xml (over 20MB's potentially) forces me to use SAX. I am relatively new to VB6 and I have no experience in SAX parsing. I have looked around online but even the best resource I have found (http://www.developerfusion.com/article/84405/sax-and-vb-6/) gives me little insight into how to combine grandchilren tags with existing attributes to make one longer attribute for a renamed tag.

I have the basic framework setup (as shown on the linked site). I think I might be able to limit most of the heavy lifting to two or three sub procedures (the first four lines in _startDocument, grab the description tag with _startElement, put the description into the function tag with endElement). However my lack of VB6/SAX knowledge is really hurting me here. Any help would be greatly appreciated.

Here is what the XML looks like Now;

<errordetails>
<error desc=”Count: 2”/>
<error desc=”System: System X”/>
<error desc=”Reason: Reason X”/>
   <functions>
      <function name=”x1” Description=”y1”>
         <violations count="2">
            <violation><source>admin</source><description>the first reason</description></violation>
            <violation><source>admin</source><description>the second reason</description></violation>
         </violations>  
      </function>
      <function name=”x2” Description=”y2”>
         <violations count="1">
           <violation><source>admin</source><description>another reason</description></violation>
        </violations>   
      </function>
   </functions>
</errordetails>

Here is what I want the xml to look like;

<errordetails>
<error desc=”Count: 2”/>
<error desc=”System: System X”/>
<error desc=”Reason: Reason X”/>
<error desc=”FunctionName: x1, FunctionDescription: y1, FunctionReason: the first reason, FunctionReason: the second reason”/>
<error desc=”FunctionName: x2, FunctionDescription: y2, FunctionReason: another reason"/>
</errordetails>

Upvotes: 2

Views: 2044

Answers (2)

k_Dank
k_Dank

Reputation: 695

I forgot to mention in my question that if the number of violations for a function was greater than 20, I only wanted the first 20 descriptions as FunctionReasons. I added the first four lines and the last line outside of the sax parsing. I get the output in another module by calling the last property 'Get XMLDoc_Function()'. Here is what I got;

Option Explicit

Implements IVBSAXContentHandler

Dim m_oContentHandler As IVBSAXContentHandler
Dim m_wtr_Function As MXXMLWriter40
Dim m_oAttributes As MSXML2.SAXAttributes
Dim m_DOM As MSXML2.DOMDocument40

Dim m_sAttribute As String
Dim m_sFunctionName As String
Dim m_sFunctionDescription As String
Dim m_sFunctionReason As String
Dim m_sFunctionReasonCount As Integer

Dim isDescription As Boolean




Private Sub Class_Initialize()
    Set m_wtr_Function = New MXXMLWriter40
    m_wtr_Function.omitXMLDeclaration = True
    Set m_oContentHandler = m_wtr_Function
    Set m_DOM = New MSXML2.DOMDocument40
    m_DOM.setProperty "SelectionLanguage", "XPath"
    m_sFunctionReasonCount = 0
End Sub

Private Sub Class_Terminate()
    Set m_wtr_Function = Nothing
    Set m_oContentHandler = Nothing
    Set m_oAttributes = Nothing
    Set m_DOM = Nothing
End Sub

Private Sub IVBSAXContentHandler_characters(strChars As String)
    If isDescription Then
        If m_sFunctionReasonCount < 20 Then
            m_sFunctionReason = ", FunctionReason: " & strChars
            m_sAttribute = m_sAttribute & m_sFunctionReason
            m_sFunctionReasonCount = m_sFunctionReasonCount + 1
            isDescription = False
        End If
    End If
End Sub

Private Property Set IVBSAXContentHandler_documentLocator(ByVal RHS As MSXML2.IVBSAXLocator)

End Property

Private Sub IVBSAXContentHandler_endDocument()

End Sub

Private Sub IVBSAXContentHandler_endElement(strNamespaceURI As String, strLocalName As String, strQName As String)

    Select Case strQName
        Case "function"
            m_oAttributes.addAttribute "", "desc", "desc", "xs:string", m_sAttribute
            m_oContentHandler.startElement strNamespaceURI, "error", "error", m_oAttributes
            m_oContentHandler.endElement strNamespaceURI, "error", "error"
            m_sAttribute = ""
            m_sFunctionReasonCount = 0
    End Select

End Sub

Private Sub IVBSAXContentHandler_endPrefixMapping(strPrefix As String)

End Sub

Private Sub IVBSAXContentHandler_ignorableWhitespace(strChars As String)

End Sub

Private Sub IVBSAXContentHandler_processingInstruction(strTarget As String, strData As String)

End Sub

Private Sub IVBSAXContentHandler_skippedEntity(strName As String)

End Sub

Private Sub IVBSAXContentHandler_startDocument()

    m_oContentHandler.startDocument

End Sub



Private Sub IVBSAXContentHandler_startElement(strNamespaceURI As String, strLocalName As String, strQName As String, ByVal oAttributes As MSXML2.IVBSAXAttributes)

    Select Case strQName
        Case "functions"
            'do nothing

        Case "function"
            Set m_oAttributes = New SAXAttributes40
            m_sFunctionName = oAttributes.getValueFromQName("name")
            m_sAttribute = "FunctionName: " & m_sFunctionName
            m_sFunctionDescription = oAttributes.getValueFromQName("Description")
            m_sAttribute = m_sAttribute & ", FunctionDescription: " & m_sFunctionDescription

        Case "description"
            isDescription = True

    End Select

End Sub


Private Sub IVBSAXContentHandler_startPrefixMapping(strPrefix As String, strURI As String)

End Sub

Public Property Get XMLDoc_Function() As Variant
    XMLDoc_Function = m_wtr_Function.output
End Property

Upvotes: 0

Bob77
Bob77

Reputation: 13267

Have you read things like the old article The Joy of SAX: a Visual Basic Sample?

It is hard to tell you much more. SAX is pretty simple really, you just need to approach it much as you should any VB6 Form, as a state machine. This means most of the logic you'll write will manage state, like accumulating and emitting transformed data as it is fed to you through the events.

Upvotes: 2

Related Questions