XML to List (Arrays)

bishmedia

Member
Licensed User
Longtime User
I'm having real issues in assigning a simple external XML file to a list view and have been given loads of options which i cannot get my head around, my last was to create a 'List' which im having difficulty with....

By calling for 'bandName' i can get the results required but my question is how can i get year, date, compName, section, position & conductor in the same 'List' and search arrays as needed??

Using Log(List1) i get the following....

(ArrayList) [Melton]
(ArrayList) []
(ArrayList) []
(ArrayList) []
...........etc

Im guessing List1 would need to be a dynamic array, hope someone can help me here :)

B4X:
Sub Parser_EndElement (Uri As String, Name As String, Text As StringBuilder)
Dim List1 As List
List1.Initialize

   If parser.Parents.IndexOf("result") > -1 Then
      If Name = "bandName" Then
         Title = Text.ToString
         List1.Add(Title)         
      End If
   End If   
End Sub

B4X:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<datas xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <comp>
      <result>
         <year>2013</year>
         <date>19th January 2013</date>
         <compName>Butlins Mineworkers</compName>
         <section>Championship</section>
         <bandName>Virtuoso GUS</bandName>
         <position>1</position>
         <conductor>John Berryman</conductor>
      </result>
   </comp>
</datas>
 

sorex

Expert
Licensed User
Longtime User
have a look at the XOM XML parser, it's a lot easier than the SAX method you try to use there.

no need to have extra lists, just random access the XML data via XOM

XOM
 
Upvote 0

bishmedia

Member
Licensed User
Longtime User
Phew looks mind blowing!!!

How can you get an external XML on the following line ....

Dim XmlString As String=File.GetText(File.DirAssets, "weather.xml")
 
Upvote 0

warwound

Expert
Licensed User
Longtime User
Here's the available options:

  • BuildFromFile (FilePath As String, Tag As Object)
    Build an XOMDocument from the file specified by FilePath.
    Tag - Pass any Object as the Tag and when the method has completed, the Tag Object is returned in the BuildDone event.
  • BuildFromInputStream (InputStream1 As InputStream, BaseUri As String, AutoCloseStream As Boolean, Tag As Object)
    Build an XOMDocument from InputStream1.
    Tag - Pass any Object as the Tag and when the method has completed, the Tag Object is returned in the BuildDone event.
  • BuildFromString (XmlString As String, BaseUri As String, Tag As Object)
    Build an XOMDocument from the XmlString.
    Tag - Pass any Object as the Tag and when the method has completed, the Tag Object is returned in the BuildDone event.
  • BuildFromURL (Url As String, Tag As Object)
    Build an XOMDocument from the document specified by Url.
    Tag - Pass any Object as the Tag and when the method has completed, the Tag Object is returned in the BuildDone event.
    Note that your application will require android.permission.INTERNET if you use this method.

The BuildFromURL method is what you're looking for.

Martin.
 
Upvote 0

bishmedia

Member
Licensed User
Longtime User
I'm not at my PC till tomorrow but will the following effect the end user!!!

Note that your application will require android.permission.INTERNET if you use this method.
 
Upvote 0

warwound

Expert
Licensed User
Longtime User
Try this:

B4X:
Sub Process_Globals
End Sub

Sub Globals
End Sub

Sub Activity_Create(FirstTime As Boolean)
   Dim XOMBuilder1 As XOMBuilder
   XOMBuilder1.Initialize("XOMBuilder1")
   
   XOMBuilder1.BuildFromURL("http://www.bishmedia.co.uk/default/Apps/xmldata.xml", Null)
End Sub

Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)
End Sub

Sub XOMBuilder1_BuildDone(XOMDocument1 As XOMDocument, Tag As Object)
   If XOMDocument1=Null Then
      '   XOMDocument1 will be Null if an error has occurred
      Log("An error has occured and the XOMDocument has NOT been created")
   Else
      Log("XOMDocument successfully created")
      Dim RootElement As XOMElement=XOMDocument1.RootElement   '   this will be the <datas> element/tag
      Dim CompElement As XOMElement=RootElement.GetFirstChildElementByName("comp")
      Dim ResultElements As XOMElements=CompElement.GetChildElementsByName("result")
      
      Log(ResultElements.Size)
      
   End If
End Sub

That successfully fetches and parses your XML file and logs 756 'result' elements found.

Look here: http://www.b4x.com/forum/additional-libraries-classes-official-updates/23551-lib-xom.html#post136448
There you will see the XOM library reference, look at the XOMElement and XOMElements methods and you'll find how to extract the info you need.

Martin.
 

Attachments

  • bishmedia.xip.zip
    5.9 KB · Views: 156
Upvote 0

bishmedia

Member
Licensed User
Longtime User
You da man :)

How would i use a method... like this ??

Sub GetElement (Index As Int) As XOMElement
'Put something here????'
End Sub
 
Upvote 0

warwound

Expert
Licensed User
Longtime User
You ideally ought to make the ResultElements XOMElements object into a process global or a global object.

Then you can access it anywhere in the activity code:

B4X:
Sub Process_Globals
   Dim ResultElements As XOMElements
End Sub

Sub Globals

End Sub

Sub Activity_Create(FirstTime As Boolean)
   If ResultElements.IsInitialized=False Then
      Dim XOMBuilder1 As XOMBuilder
      XOMBuilder1.Initialize("XOMBuilder1")
      XOMBuilder1.BuildFromURL("http://www.bishmedia.co.uk/default/Apps/xmldata.xml", Null)
   Else
      BuildListView
   End If
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub XOMBuilder1_BuildDone(XOMDocument1 As XOMDocument, Tag As Object)
   If XOMDocument1=Null Then
      '   XOMDocument1 will be Null if an error has occurred
      Log("An error has occured and the XOMDocument has NOT been created")
   Else
      Log("XOMDocument successfully created")
      Dim RootElement As XOMElement=XOMDocument1.RootElement   '   this will be the <datas> element/tag
      Dim CompElement As XOMElement=RootElement.GetFirstChildElementByName("comp")
      Dim ResultElements As XOMElements=CompElement.GetChildElementsByName("result")
      
      Log(ResultElements.Size)
      
   End If
   
   BuildListView
End Sub

Sub BuildListView
   '   here i'd imagine you'd populate your ListView
End Sub

You can now access ResultElements anywhere in the activity code.
If the user changes the device orientation then the ResultElements will remain and you'll not have to download and parse the XML again.

So no need for a GetElement Sub, just use code such as:

B4X:
Dim ResultElement As XOMElement=ResultElements.GetElement(your element index here)

Martin.
 
Upvote 0

bishmedia

Member
Licensed User
Longtime User
Ok im feeling really thick now as ive just wasted an hour trying to figure out how to populate a listview :-(

Please forgive me XOM is new to me and there are no tutorials on here :-(

All i need now is to know what i wopuld need to say populate the listview with 'compName' ??

I really do appreciate your help :sign0085:
 
Upvote 0

warwound

Expert
Licensed User
Longtime User
This example should help:

B4X:
Sub Process_Globals
   Dim ResultElements As XOMElements
End Sub

Sub Globals
   Dim ListView1 As ListView
End Sub

Sub Activity_Create(FirstTime As Boolean)
   ListView1.Initialize("ListView1")
   Activity.AddView(ListView1, 0, 0, 100%x, 100%y)
   
   If ResultElements.IsInitialized=False Then
      Dim XOMBuilder1 As XOMBuilder
      XOMBuilder1.Initialize("XOMBuilder1")
      XOMBuilder1.BuildFromURL("http://www.bishmedia.co.uk/default/Apps/xmldata.xml", Null)
   Else
      BuildListView
   End If
End Sub

Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)
End Sub

Sub XOMBuilder1_BuildDone(XOMDocument1 As XOMDocument, Tag As Object)
   If XOMDocument1=Null Then
      '   XOMDocument1 will be Null if an error has occurred
      Log("An error has occured and the XOMDocument has NOT been created")
      '   now handle the failure to get and parse the XML
      
   Else
      Log("XOMDocument successfully created")
      Dim RootElement As XOMElement=XOMDocument1.RootElement   '   this will be the <datas> element/tag
      Dim CompElement As XOMElement=RootElement.GetFirstChildElementByName("comp")
      Dim ResultElements As XOMElements=CompElement.GetChildElementsByName("result")
      
      BuildListView
   End If
   
End Sub

Sub BuildListView
   Dim i As Int
   Dim CompNameElement As XOMElement
   Dim ResultElement As XOMElement
   
   For i=0 To ResultElements.Size-1
      ResultElement=ResultElements.GetElement(i)
      CompNameElement=ResultElement.GetFirstChildElementByName("compName")
      
      ListView1.AddSingleLine2(CompNameElement.Value, ResultElement)
   Next
   
End Sub

Sub ListView1_ItemClick (Position As Int, Value As Object)
   Log("ListView1_ItemClick")
   
   Dim ResultElement As XOMElement=Value
   Dim Names() As String=Array As String("year", "date", "compName", "section", "bandName", "position", "conductor")
   Dim i As Int
   
   For i=0 To Names.Length-1
      Log(Names(i)&" : "&ResultElement.GetFirstChildElementByName(Names(i)).Value)
   Next
   
   Log("********************")
End Sub

Martin.
 

Attachments

  • bishmedia_ListViewzip.zip
    6.3 KB · Views: 156
Upvote 0

bishmedia

Member
Licensed User
Longtime User
Thats amazing, its just what i need, how you knock it up so quick is beyond me!!!

Is it really difficult to make it a unique value??
 
Upvote 0

warwound

Expert
Licensed User
Longtime User
You can use whatever you want for the list item text:

B4X:
Sub BuildListView
   Dim i As Int
   Dim ListTitle As String
   Dim ResultElement As XOMElement
   
   For i=0 To ResultElements.Size-1
      ResultElement=ResultElements.GetElement(i)
      
      ListTitle=ResultElement.GetFirstChildElementByName("bandName").value
      
      '   or try uncommenting this
      '   ListTitle=ResultElement.GetFirstChildElementByName("bandName").value&" "&ResultElement.GetFirstChildElementByName("date").value
      
      ListView1.AddSingleLine2(ListTitle, ResultElement)
   Next
   
End Sub

If each 'result' element does not have a unique value that is suitable then you can create one by combining two values - uncomment that line and you'll see what i mean.

I bet your next question is how to sort the result elements...
XOM has no built in sort methods so you'd probably have to extract all the values from the XML, store them in a List of Lists or a List of Maps and then sort the List.
I won't have time to help tonight - gonna go watch some telly!

Martin.
 

Attachments

  • bishmedia_ListView_2.zip
    6.3 KB · Views: 146
Upvote 0

bishmedia

Member
Licensed User
Longtime User
Now i am really confused, everything works great just needing 'Unique', its a real must.

I started on Arrays and was told to try Lists, then to try XOM and now to try Lists!! I'm soooooo confused, it seems one way doesn't cover all!!

Just to give you an idea, a link to my App is below, i have my app built but i used PHP and Webview but didnt think it looked professional enough, just look at the database tab and youll see what im trying to achieve!!!!

database
 
Upvote 0

warwound

Expert
Licensed User
Longtime User
Looking at your WebView based app i see a possible solution.

You have a web page with two search forms: 'Search by competition' and 'Search by band name'.
You could create two activities in your new non WebView app: 'Competition finder' and 'Band finder'.
Each activity would replicate the form elemnts of the web based search, 'Competition finder' would have three Spinners and a Button for example.
The user selects the items they are interested in from the Spinners and click the Button, your app makes an http request to your server for the required items and displays it in ListView - each of these search results would have a unique value that could be used in the ListView?
(Remember ListView items can have two lines instead of one so that may be a way to create unique list items).

The Band finder activity would have one Spinner and a Button and after the Spinner item is selcted and Button clicked you'd request and display the XML as a ListView.

If you make your searches so that each item in the search result has a unique value or if you can use two lines in a ListView then your problem is solved.

Martin.
 
Upvote 0

bishmedia

Member
Licensed User
Longtime User
Thanks Martin for looking.

What you suggested is what ive been working on and with your help i have been able to extract the records which has helped me immensely.

I'm gonna hard code for now the competition, section & year into a spinner (which i need to study) because im finding trying to get a unique value far beyond my capabilities, then when the user clicks the 'search' button the competition results are shown as per my current App.

I'm truly grateful for all your help given

Regards

Bish
 
Upvote 0

jeng

Member
Licensed User
Longtime User
XOMBuilder

Hello,


B4X:
<oscam version="1.20-unstable_svn build r8599" revision="8599" starttime="2013-04-05T23:19:41+0200" uptime="14661" readonly="0"><status>
<client type="s" name="root" desc="" protocol="server" protocolext="" au="0" thid="0xa0cf3f0">
<request caid="0000" srvid="0000" ecmtime="" ecmhistory="" answered=""/>
<times login="2013-04-05T23:19:41+0200" online="14661" idle="1"/>
<connection ip="127.0.0.1" port="0">OK</connection>
</client>
<client type="r" name="imagin" desc="" protocol="mouse" protocolext="" au="-1" thid="0xa0d7db0">
<request caid="0000" srvid="0000" ecmtime="" ecmhistory="" answered=""/>
<times login="2013-04-05T23:19:41+0200" online="14661" idle="14661"/>
<connection ip="127.0.0.1" port="0">CARDOK</connection>
</client>
<client type="r" name="sat-hd+" desc="" protocol="mouse" protocolext="" au="-1" thid="0xa0d9a68">
<request caid="0000" srvid="0000" ecmtime="" ecmhistory="" answered=""/>
<times login="2013-04-05T23:19:41+0200" online="14661" idle="14661"/>
<connection ip="127.0.0.1" port="0">CARDOK</connection>
</client>
</status>
<log></log>
</oscam>

I use the example "bishmedia", the only result i have is that i can get the CARDOK status but cannot filter ex: ip port etc...

can you help me please?
:BangHead:

Here the code:
B4X:
Sub Process_Globals
   Dim ResultElements As XOMElements
End Sub

Sub Globals
   Dim ListView1 As ListView
End Sub

Sub Activity_Create(FirstTime As Boolean)
   ListView1.Initialize("ListView1")
   Activity.AddView(ListView1, 0, 0, 100%x, 100%y)
   
   If ResultElements.IsInitialized=False Then
      Dim XOMBuilder1 As XOMBuilder
      XOMBuilder1.Initialize("XOMBuilder1")
      'XOMBuilder1.BuildFromURL("http://www.bishmedia.co.uk/default/Apps/xmldata.xml", Null)
      XOMBuilder1.BuildFromURL("http://localhost:8181/oscamapi.html?part=status", Null)
   Else
      BuildListView
   End If
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub XOMBuilder1_BuildDone(XOMDocument1 As XOMDocument, Tag As Object)
   If XOMDocument1=Null Then
      '   XOMDocument1 will be Null if an error has occurred
      Log("An error has occured and the XOMDocument has NOT been created")
      '   now handle the failure to get and parse the XML
      
   Else
      Log("XOMDocument successfully created")
      Dim RootElement As XOMElement=XOMDocument1.RootElement   '   this will be the <datas> element/tag
      'Dim CompElement As XOMElement=RootElement.GetFirstChildElementByName("comp")
      'Dim ResultElements As XOMElements=CompElement.GetChildElementsByName("result")
      Dim CompElement As XOMElement=RootElement.GetFirstChildElementByName("status")
      Dim ResultElements As XOMElements=CompElement.GetChildElementsByName("client")
      
      BuildListView
   End If
   
End Sub

Sub BuildListView
   Dim i As Int
   Dim ListTitle As String
   Dim ResultElement As XOMElement
   
   For i=0 To ResultElements.Size-1
      ResultElement=ResultElements.GetElement(i)
      
      'ListTitle=ResultElement.GetFirstChildElementByName("bandName").value
      ListTitle=ResultElement.GetFirstChildElementByName("connection").value
      
      '   or try uncommenting this
      '   ListTitle=ResultElement.GetFirstChildElementByName("bandName").value&" "&ResultElement.GetFirstChildElementByName("date").value
      
      ListView1.AddSingleLine2(ListTitle, ResultElement)
   Next
   
End Sub

Sub ListView1_ItemClick (Position As Int, Value As Object)
   Log("ListView1_ItemClick")
   
   Dim ResultElement As XOMElement=Value
   
   Dim Names() As String=Array As String("type", "name", "desc", "protocol", "protocolext", "au", "thid")
   Dim i As Int
   
   For i=0 To Names.Length-1
      Log(Names(i)&" : "&ResultElement.GetFirstChildElementByName(Names(i)).Value)
   Next
   
   Log("********************")
End Sub
 
Last edited:
Upvote 0
Top