Android Question How can I pass an InputSource object into XMLBuilder.Parse?

BenF

Member
Licensed User
Longtime User
Hi all,
Sorry if this is a particularly dense question.... I am trying to find a way of reading a local xml file into my app, and then adding additional elements to it, as additional data is entered by the user.

Context: The user will need to enter multiple (up to 30) samples with a range of values (date, time, sample type etc, potentially up to ~50/sample). Rather than try to record the values for all samples into an array and build the xml with a single builder, I thought it would be easier to enter the values into the xml as each sample entry is completed, and then enter the next sample with a new builder, parsed from the previous file. The xml layout is predefined, as per the database that I am passing data to.

I have been able to use the xmlBuilder to build the file in the first place (ie the first sample) , but I am getting stuck with parsing the file back into the xmlBuilder. I believe I need to use xmlBuilder.Parse, as mentioned here:
https://www.b4x.com/android/forum/threads/anyone-using-xmlbuilder-with-b4a.16277/
in posts #9 and #10.
However, the .Parse requires an InputSource object, and I cannot figure out how to get the InputStream from the xml into an InputSource object... - When I tried to use File.OpenInput I got an error during compiling:

B4X:
Dim x As XMLBuilder
x=x.parse(File.OpenInput(File.DirInternal,"Test1.xml"))

B4X:
Parsing code.                           0.06
Compiling code.                         0.89
Compiling layouts code.                 0.15
Generating R file.                      1.19
Compiling debugger engine code.         2.15
Compiling generated Java code.          Error
B4A line: 354
x=x.parse(File.OpenInput(File.DirInternal,\
javac 1.7.0_71
src\b4a\example\main.java:387: error: inconvertible types
_x = _x.parse((org.xml.sax.InputSource)(anywheresoftware.b4a.keywords.Common.File.OpenInput(anywheresoftware.b4a.keywords.Common.File.getDirInternal(),"Test1.xml").getObject()));
                                       ^
  required: InputSource
  found:    InputStream
1 error


The only other reference to them that I can find is through the xmlSax library, with .Parse and .Parse2:
https://www.b4x.com/android/forum/threads/xml-parsing-with-the-xmlsax-library.6866/
(post #15) mentioned as passing the stream to an InputSource object.

That made me think of trying:
B4X:
    Dim x As XMLBuilder
    Dim Parser As SaxParser

    x=x.parse(Parser.Parse(File.OpenInput(File.DirInternal,"Test1.xml"),"Parser"))

but realised pretty quickly that it's trying to pass a void value. This is where I come up against the limits of fumbling in the dark...

This is probably a result of my novice coding, but any thoughts as to how I can move forward would be appreciated!

For reference I have attached a copy of the xml format that was supplied by the target database as a template, and the test program in which I am trying to figure out the xml coding...

Cheers,
Ben.
 

Attachments

  • wasp.xml
    7.4 KB · Views: 161
  • XML test.zip
    30.4 KB · Views: 152

BenF

Member
Licensed User
Longtime User
Thanks for the quick response Erel, appreciated as always. I think I've managed it using XmlSax to parse the file, and rebuilding the xml in the event subs. I'll try to post the code for reference when I'm in the office tomorrow.

Cheers,
Ben.
 
Upvote 0

BenF

Member
Licensed User
Longtime User
Hi Erel,
Here's the code that I've come up with, seems to do the trick. I've cut down the size of the xml for ease of viewing, but retained the most of the general structure.

B4X:
Sub Globals
    Dim x As XMLBuilder
    Dim TestPanel As Panel
    Dim Parser As SaxParser
    Dim In As InputStream
    Dim Pnl As Panel
    Dim PrevLine As String
End Sub

Sub Activity_Create(FirstTime As Boolean)
   
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub Button1_Click
    x = x.create("wasp")
        x = x.element("sample_no") _
        .attribute("id","123456") _
            .element("samp_details") _
                .element("project_code") _
                    .text("GBRI5") _
                .up() _
                .element("samp_type") _
                    .text("IS") _
                .up() _
                .element("containers") _
                    .text("3") _
                .up() _
            .up() _
            .element("bottle_details") _
                .element("bottle_details1") _
                    .element("bottle_type") _
                        .text("A") _
                    .up() _
                    .element("bott_lab_code") _
                        .text("FSS") _
                    .up() _
                    .element("collect_meth") _
                        .text("MA") _
                    .up() _
                    .element("preserv_meth1") _
                        .text("CH") _
                    .up() _
                .up() _
            .up() _
            .element("test_details") _
                .element("test_details1") _
                    .element("test_code") _
                        .text("SEQEM1") _
                    .up() _
                    .element("test_lab_code") _
                        .text("FSS") _
                    .up() _
                .up _
            .up() _
        .up() _
    .up()
   
    File.WriteString(File.DirInternal, "Test1.xml", x.asString)
   
    Log(x.asString)
   
    In = File.OpenInput(File.DirInternal,"Test1.xml")
   
    Parser.Initialize
   
    Parser.Parse(In, "Parser")
    In.Close
   
    Log(x.asString)

    x = x.element("sample_no") _
        .attribute("id","123456") _
            .element("samp_details") _
                .element("project_code") _
                    .text("GBRI5") _
                .up() _
                .element("samp_type") _
                    .text("IS") _
                .up() _
                .element("containers") _
                    .text("3") _
                .up() _
            .up() _
            .element("bottle_details") _
                .element("bottle_details1") _
                    .element("bottle_type") _
                        .text("A") _
                    .up() _
                    .element("bott_lab_code") _
                        .text("FSS") _
                    .up() _
                .up() _
            .up() _
            .element("test_details") _
                .element("test_details1") _
                    .element("test_code") _
                        .text("SEQEM1") _
                    .up() _
                    .element("test_lab_code") _
                        .text("FSS") _
                    .up() _
                .up _
            .up() _
        .up() _
    .up()
   
    File.WriteString(File.DirInternal, "Test2.xml", x.asString)
    
    Log(x.AsString)
End Sub   
   
Sub Parser_StartElement (Uri As String, Name As String, Attribute As Attributes)
    If Name = "wasp" Then
        x = x.create("wasp")
    Else If Name = "sample_no" Then
        x = x.element(Name)
        x = x.Attribute("id", Attribute.GetValue2("","id"))
    Else
        x = x.element(Name)
    End If
    PrevLine = "Start"
End Sub


Sub Parser_EndElement (Uri As String, Name As String, Text As StringBuilder)
    If Name <> "wasp" Then
        If PrevLine = "Start" Then
            x = x.Text(Text)
            x = x.up()
        Else If PrevLine = "Finish" Then
            x = x.up()
        End If
    End If
    PrevLine = "Finish"
End Sub

Hopefully this will be useful to someone at some point, unless there's an easier way of doing it?

Cheers,
Ben
 
Upvote 0

BenF

Member
Licensed User
Longtime User
No, the data is passed to a third party database that has a defined xml structure for inputting data, so I do need the data stored as an xml. I'll run with this for the moment, unless it starts taking too long to rewrite the xml. Time will tell :)
 
Upvote 0
Top