Android Tutorial XML Parsing with the XmlSax library

It is simpler to parse XML with Xml2Map class: https://www.b4x.com/android/forum/threads/b4x-xml2map-simple-way-to-parse-xml-documents.74848/

The XmlSax library provides an XML Sax parser.
This parser sequentially reads the stream and raises events at the beginning and end of each element.
The developer is responsible to do something useful with those events.

There are two events:
B4X:
StartElement (Uri As String, Name As String, Attributes As Attributes)
EndElement (Uri As String, Name As String, Text As StringBuilder)
The StartElement is raised when an element begins. This event includes the element's attributes list.
EndElement is raised when an element ends. This event includes the element's text.

In this example we will parse the forum RSS feed. RSS is formatted using XML.
A simplified example of this RSS is:
B4X:
<?xml version="1.0" encoding="ISO-8859-1"?>
<rss version="2.0">
    <channel>
        <title>Basic4ppc  / Basic4android - Android programming</title>
        <link>http://www.b4x.com/forum</link>
        <description>Basic4android - android programming and development</description>
        <ttl>60</ttl>
        <image>
            <url>http://www.b4x.com/forum/images/misc/rss.jpg</url>
            <title>Basic4ppc  / Basic4android - Android programming</title>
            <link>http://www.b4x.com/forum</link>
        </image>
        <item>
            <title>Phone library was updated - V1.10</title>
            <link>http://www.b4x.com/forum/additional-libraries-official-updates/6859-phone-library-updated-v1-10-a.html</link>
            <pubDate>Sun, 12 Dec 2010 09:27:38 GMT</pubDate>
            <guid isPermaLink="true">http://www.b4x.com/forum/additional-libraries-official-updates/6859-phone-library-updated-v1-10-a.html</guid>
        </item>
        ...MORE ITEMS HERE
    </channel>
</rss>
The first line is part of the XML protocol and is ignored.
On the second line the StartElement event will be raised with "Name = rss" and the attributes will include the "version" field.
The EndElement of the rss element will only be called on the last line: </rss>.

We will populate a list view with all items parsed from an offline file. When the user will press on an item we will open the browser with the relevant link.
Every item represents a forum thread.

xmlsax_1.png


For each item we are interested in two values. The title and the link.
The SaxParser object includes a handy list that holds the names of all the current parents elements.
This is useful as it will help us find the "correct" 'title' and 'link' elements. The correct elements are the ones under the 'item' element.

The parsing code in this case is pretty simple:
B4X:
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 parser.Parents.IndexOf("item") > -1 Then
        If Name = "title" Then
            Title = Text.ToString
        Else If Name = "link" Then
            Link = Text.ToString
        End If
    End If
    If Name = "item" Then
        ListView1.AddSingleLine2(Title, Link) 'add the title as the text and the link as the value
    End If
End Sub
Title and Link are global variables.
We are only using EndElement events in this program.
First we check if we are inside an 'item' element. If this is the case we check the actual element name and save it if it is 'title' or 'link'.

If the current element is 'item' it means that we are done parsing an item.
So we add the data collected to the list view.

We are using ListView.AddSingleLine2. This method receives two values. The first is the item text and the second is the value that will return when the user will click on this item. In this case we are storing the link as the return value.

Later we will use it to open the browser:
B4X:
Sub ListView1_ItemClick (Position As Int, Value As Object)
    StartActivity(PhoneIntents1.OpenBrowser(Value)) 'open the brower with the link
End Sub
The code that initiated the parsing is:
B4X:
    Dim in As InputStream
    in = File.OpenInput(File.DirAssets, "rss.xml") 'This file was added with the file manager.
    parser.Parse(in, "Parser") '"Parser" is the events subs prefix.
    in.Close
 

Attachments

  • XmlSax.zip
    10 KB · Views: 6,055
Last edited:

JOTHA

Well-Known Member
Licensed User
Longtime User
Is it possible to use the XmlSax with a given XML-File like this one?

B4X:
<xml>
<entries ext="Export" extxmlversion="1.1" type="saved" encrypt="false">
<entry host="http://www.jothasoft.de" user="joggele" vorname="juergen" nachname="hollmann" strasse="teststrasse 11" plz="73525" cityx="testcity"/>
<entry host="http://www.jothasoft.de" user="joggele2" vorname="juergen2" nachname="hollmann2" strasse="teststrasse 22" plz="73525" cityx="testcity"/>
</entries>
</xml>

I want to get 2 or (many) more rows with 7 columns and put them into TextEdit fields or into an SQLite table ...

Does someone know if this could work witht that given XML-File above?
THX
 

JOTHA

Well-Known Member
Licensed User
Longtime User
Hello Erel,

thank you for your quick response.
I meant if this is a valid xml-string becaue there is only "</entries>" at the end, but no "<entries>" at the beginning?

If it is valid, the next step is to find out, how to get the Data into a table ... ;)
 

JOTHA

Well-Known Member
Licensed User
Longtime User
Thank you Erel for the tip!

I have seen that, but I didn't know that it is a valid Xml-String. :)
 

arnold steger

Member
Licensed User
Longtime User
I need help for this question.
Want parse a kml file and maked from any Polyline a txt file.
I have a problem when want finde a name for separatly the polyline and convert my string whit all my latlon in a list

B4X:
Sub Globals
    Dim TempName,TempAllCoords,TempCoords As String
    Dim TempAllList,SafeList As List

End Sub
Sub Parser_EndElement (Uri As String, Name As String, Text As StringBuilder)
    If parser.Parents.IndexOf("Document") > -1 Then
        If Name="td" Then
        TempName=Text.ToString
        End If
  
        If Name = "coordinates" Then
        SafeList.Initialize
        TempAllCoords=Text.ToString
        TempCoords=TempAllCoords.Replace("0 ","")
        Dim PolygonCoords1 () As Double=Array As Double(TempCoords) 'to convert string to double
        Dim PolygonPoints1 As List=CoordsToLatLngList1(PolygonCoords1)
        For i = 1 To PolygonPoints1.Size-1
        Dim PointsTemp() As String = Regex.Split(",",PolygonPoints1.Get(i))
            Dim ln As LatLng
            ln.Initialize(PointsTemp(0),PointsTemp(1))
            SafeList.Add(ln)
        Next
  
        Dim Writer As TextWriter
        Writer.Initialize(File.OpenOutput(File.DirRootExternal & "/Grenzen",TempName&".txt",True))
        Writer.WriteList(SafeList)
        Writer.Close
        End If
    End If

End Sub

Sub CoordsToLatLngList1(PolygonCoords1() As Double) As List
    Dim PolygonCoords1Count As Int=PolygonCoords1.Length
    Dim LatLngList1 As List
    LatLngList1.Initialize
    Dim i As Int
    For i=0 To PolygonCoords1.Length-2 Step 2
        Dim LatLng1 As LatLng
        LatLng1.Initialize(PolygonCoords1(i), PolygonCoords1(i+1))
        LatLngList1.Add(LatLng1.Longitude&LatLng1.Latitude)
    Next
    Return LatLngList1
End Sub
 

Attachments

  • KML.txt
    14.3 KB · Views: 444
Last edited:

samikinikar

Member
Licensed User
Longtime User
Can someone help with a example of image downloading along with XML contents, My basic requirements is display the listview with the thumbnail,title and the abstract,
I am able to get the title and the abstract with the examples given with this library but not the images.

Also if possible, after click on the image or title in the listview, the detail view( the whole content of the abstract) to be displayed., right now the example opens the browser to display the content or image.

MyXML file is attached.
 

Attachments

  • myxml.xml
    67.3 KB · Views: 400
  • myxml.xml
    67.3 KB · Views: 413

Shay

Well-Known Member
Licensed User
Longtime User
I have Hebrew in my XML (title field) and library is crashing
is the issue with this library or with downloading the file?

I am using OkHTTP2util
B4X:
MainMenu, Response from server: <?xml version="1.0" encoding="windows-1255"?>
<rss version="2.0">
    <channel>
       
        <item>
            <title>���</title> <--------- should be Hebrew
            <color>5</color>
            <link>1</link>
            <description>none</description>
        </item>
        <item>
            <title>bbb</title>
            <color>6</color>
            <link>2</link>
            <description>none</description>
        </item>
    </channel>
</rss>
Error occurred on line: 103 (MainMenu)
org.apache.harmony.xml.ExpatParser$ParseException: At line 7, column 10: not well-formed (invalid token)
    at org.apache.harmony.xml.ExpatParser.parseFragment(ExpatParser.java:515)
    at org.apache.harmony.xml.ExpatParser.parseDocument(ExpatParser.java:474)
    at org.apache.harmony.xml.ExpatReader.parse(ExpatReader.java:321)
    at org.apache.harmony.xml.ExpatReader.parse(ExpatReader.java:279)
    at anywheresoftware.b4a.objects.SaxParser.parse(SaxParser.java:80)
    at anywheresoftware.b4a.objects.SaxParser.Parse(SaxParser.java:73)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:702)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:339)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:246)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:134)
    at anywheresoftware.b4a.BA$2.run(BA.java:328)
    at android.os.Handler.handleCallback(Handler.java:615)
    at android.os.Handler.dispatchMessage(Handler.java:92)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:4921)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794)
    at dalvik.system.NativeStart.main(Native Method)
** Service (starter) Destroy **
** Activity (mainmenu) Pause, UserClosed = true **
** Service (widget) Start **
 
Last edited:

GaNdAlF89

Active Member
Licensed User
Longtime User
I have a field <Result> in my xml response. Depending on value of this field, the next fields are different. How can I do to parse them correctly?
 

awakenblueheart

Member
Licensed User
Longtime User
Need help. Why I am getting this error? I search it is related to '=' on the URL inside the xml.

org.apache.harmony.xml.ExpatParser$ParseException: At line 6, column 64: not well-formed (invalid token)

Here my code:

B4X:
Dim in As InputStream
    in = File.OpenInput(File.DirAssets, "rss2.xml") 'This file was added with the file manager.
    parser.Initialize
    Dim tr As TextReader
    tr.Initialize2(in, "ISO-8859-15")
    parser.Parse2(tr,"Parser")   
    in.Close

Attached the xml file.
 

Attachments

  • rss2.xml
    103.6 KB · Views: 414

Erel

B4X founder
Staff member
Licensed User
Longtime User
It is not a valid XML string. Ampersands in text nodes should be escaped (&amp;).

This code works:
B4X:
Dim s As SaxParser
s.Initialize
Dim text As String = File.ReadString(File.DirAssets, "rss2.xml")
text = text.Replace("&", "&amp;")
Dim in As InputStream
Dim b() As Byte = text.GetBytes("UTF8") '<--- it is UTF8 file.
in.InitializeFromBytesArray(b, 0, b.Length)
s.Parse(in, "s")
 
Top