Reputation: 695
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
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
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