B4J Question XMLSax Test please

stevel05

Expert
Licensed User
Longtime User
Could someone test the attached project for me please?

It just parses a small (2kb) SVG file using XMLSax and XML2Map code module. I have validated the XML using an online validation tester.

The problem I'm having is that it is taking 15.5 seconds to parse on B4j. Running the same thing on Android is taking 37ms. I just want to make sure I'm not going mad (too late I know).

I've checked that there are no old versions of jXMLSax in my additional libraries folder.

Please let me know your results.

Thanks in advance.
 

Attachments

  • ParseSVG.zip
    4.2 KB · Views: 255
Last edited:

stevel05

Expert
Licensed User
Longtime User
Thanks Daestrum, I will dig a bit deeper then. Just wanted to make sure it wasn't my software setup.
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
adding various logs to time each section, it looks like parser.parse(…) is the killer in the app. (Takes over 99% of the time)
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
Hmm, I've just checked to see if it's trying to validate the XML against an external source while parsing, but it appears not.
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
Also running in B4j using the B4a library gives the same result.
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
Found it! it was downloading a definition file from http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd, which is very slow to respond. I found a solution on the internet which was to download the file and set an Entity resolver handler which passes the downloaded file as an input source.

If you are interested, I got the solution from here: https://stackoverflow.com/questions/15928583/serious-performance-issues-with-java-sax

And changed the code in XML2Map to:

B4X:
Public Sub Initialize
    parser.Initialize
    Dim R As Reflector
    R.Target = parser
    Dim ParserJO As JavaObject = R.GetField("sp")
    Dim ER As Object = ParserJO.CreateEvent("org.xml.sax.EntityResolver","ResolveEntity",Null)
    ParserJO.RunMethodJO("getXMLReader",Null).RunMethod("setEntityResolver",Array(ER))
End Sub

Public Sub ResolveEntity_Event (MethodName As String, Args() As Object) As Object
    Log("ResolveEntity_Event")
    Dim InputSource As JavaObject
    InputSource.InitializeNewInstance("org.xml.sax.InputSource",Array(File.OpenInput(File.DirAssets,"svg10.dtd")))
    Return InputSource
End Sub

Time taken is now 55ms. Much better.
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
I'm not sure why the Android version does not attempt to download the dtd file, presumably because it's mobile. It must have some definitions included that it uses.
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
One more update, returns an empty string as the dtd, Parse time down to 8 ms, that's more like it.

B4X:
Sub Class_Globals
    Private parser As SaxParser
    Type XmlElement (Name As String, Children As List, Text As String, Attributes As Map)
    Private elements As List
    Private InputSource As JavaObject
End Sub

Public Sub Initialize
    parser.Initialize
   
    Dim StringReader As JavaObject
    StringReader.InitializeNewInstance("java.io.StringReader",Array(""))
    InputSource.InitializeNewInstance("org.xml.sax.InputSource",Array(StringReader))
   
    Dim R As Reflector
    R.Target = parser
    Dim ParserJO As JavaObject = R.GetField("sp")
    Dim ER As Object = ParserJO.CreateEvent("org.xml.sax.EntityResolver","ResolveEntity",Null)
    ParserJO.RunMethodJO("getXMLReader",Null).RunMethod("setEntityResolver",Array(ER))
End Sub

Public Sub ResolveEntity_Event (MethodName As String, Args() As Object) As Object
    Return InputSource
End Sub
 
Upvote 0
Top