While parsing xml using the SAX library, for some reason the events are not being fired, at least the end event isn't as that's the one I'm interested in.
The frustrating thing is that this was working last night. What I did change was to use multiple Parser objects in the same code module, each using a different event name. This was necessary because the first API call results in a SessionID, I use that session id to build a URL, then after the user is done with the auth in a webview, the app uses the API to get an access token and so on. I know I could have perhaps done it all with one parser object but thought my code would be cleaner. But now even if I remove all the code and just have a session id code as below with only one Parser object present in the code module, it still doesn't trigger the events.
Has anyone got an idea as to why this might be happening?
B4X:
Sub ParseSessionId(ResponseXML As InputStream)
Dim parser1 As SaxParser
parser1.Initialize
parser1.Parse(ResponseXML,"Parser")
End Sub
Sub Parser_StartElement (Uri As String, Name As String, Attributes As Attributes)
End Sub
Sub Parser_EndElement (Uri As String, Name As String, Text As StringBuilder)
If Not(RequestSuccessful) Then
Return
End If
If Name = "Ack" Then
If Text.ToString <> "Success" Then
RequestSuccessful = False
End If
Else If Name="SessionID" Then
SessionId = Text
Log("SessionID = " & SessionId)
End If
End Sub
Thanks TDS.
That could be the reason but I'm finding it hard to understand why. From what I understand about SAX, it is a stream parser and its implementation is usually synchronous. That is, the parse method should not return unless it has gone over the entire document. And until that time, parser1 should be in scope. However, internally, the SAX library might be relying on it being a global?
But none of this explains why it will work sometimes and at other times it will simply die quietly.
I have just done another test which is:
B4X:
Sub Activity_Create(FirstTime As Boolean)
Dim p As SaxParser
p.Initialize
p.Parse(File.OpenInput(File.DirAssets,"get_session_id_request.xml"),"p")
End Sub
Sub p_StartElement (Uri As String, Name As String, Attributes As Attributes)
End Sub
Sub p_EndElement (Uri As String, Name As String, Text As StringBuilder)
Log("Name="&Name&", Text="& Text)
End Sub
Did I miss where it says that P.Parse is synchronous? Because it wouldnt be able to raise any events if it were.
Why it works sometimes and not other times? Because the GC takes its time to clear the local variables, maybe the file is parsed fast enough before GC destroys it?
Did I miss where it says that P.Parse is synchronous? Because it wouldnt be able to raise any events if it were.
Why it works sometimes and not other times? Because the GC takes its time to clear the local variables, maybe the file is parsed fast enough before GC destroys it?
OK. So what you are suggesting that the 'parse' method can return before the parsing of the document is completed?
As to why I think it is synchronous is because I'm thinking these are callback methods(kind of like using event handlers in anonymous classes in java). So the parser reads the elements one by one, raises start and end as it finds it and calls the appropriate method *before* moving on to the next one. Also, with SAX I believe the parser does not need to raise events asynchronously as then it won't be a streaming parser would it?
You are actually right. It can indeed be synchronous.
I'm a bit disappointed its synchronous, I would have hoped such an operation be run on a background thread. Although thinking more, then it would probably block the processing thread with these events, so maybe thats not a good idea either.
Well with all this discussion in the background, my problem still kind of stands as-is
I am trying to use a parser in a code module. Is that also not where it should be used? Does it have to used inside an activity, service or class module?