parsing XML question

I’m getting an xml feed and trying to extract some data. With tags like

Joseph
it works just fine.

but with With tags like:
30

I get this error:

/tmp/plugin/HJAAAAREIkOr/pkg:/source/main.brs(33): runtime error ec: ‘Dot’ Operator attempted with invalid BrightScript Component or interface reference.

033: tcs=xml.file-count.GetText()

and:

tcs &h30 Untyped val:Uninitialized

Can anyone help? How do get the value of a tag that has subsidiary information in it like “type”? Should I declare tcs as an integer first? It doesn’t seem to help. Do I need to do a test of some kind on each xml key before I attempt to assign it to a variable?

Thanks!

“-” is not a valid variable character. Use one of the alternate access methods, such as a member function, to access the element. The Reference manual mentions this when referring to the need to do case sensitive matching, so it will most likely work here as well.

Ok, looks like you are correct that the - is the cause of the problem. Now how do I get that xml tag without using the dash character - it is in the xml feed and there are many other xml tags that have that character as well

The roXMLElement component has a GetNamedElements() method. You should be able to use that to get an roXMLList of the “file-count” elements that you can loop through.

Thanks for responding. I don’t see any examples of actual usage of GetNamedElement in the documentation. I’m searching through the examples also, and the videoplayer which actually parses XML doesn’t use this function. Can you post an example of how GetNamedElement is actually used?

In your case it would be:

xml.GetNamedElement("file-count")[0].GetText()

Thanks! So, how would one know that a function like GetNamedElement would be called like this, as opposed to xml.tagname.GetNamedElement() ?

What do I look for when reading the Developer manual to know if a function gets called like:

something.Function() or if it gets called like:

Function(“something”)

In other words, how did you come up with that statement and know that it works?

  • Joel

It is documented in the SDK. Look at section 10.16 in the Brightscript Reference Manual. There are also some examples in the generalUtil.brs files found in some of the example channels.

Thanks, I read the manual section you suggested again, and I understand a little bit better now. However, I still don’t understand all the aspects of that code you posted. What is the [0] about, seems like an array reference, but why is it needed when there is already the name of the tag in the parenthesis:

xml.GetNamedElement(“file-count”)[0].GetText()

Thanks,

Joel

“jbrave” wrote:
Thanks, I read the manual section you suggested again, and I understand a little bit better now. However, I still don’t understand all the aspects of that code you posted. What is the [0] about, seems like an array reference, but why is it needed when there is already the name of the tag in the parenthesis:

xml.GetNamedElement(“file-count”)[0].GetText()

Thanks,

Joel
The name of the method is actually GetNamedElements and it returns an roXMLList, so you need to get the first index of that list to get the XML element you’re looking for. The safest way to do this is probably…


xmlFileCount = xml.GetNamedElements("file-count")
If xmlFileCount <> invalid And fileCount.Count() > 0 Then
    fileCount = xmlFileCount[ 0 ].GetText()
End If

With that, you won’t blow up if the element is missing from your XML for some reason.

Thanks for catching that typo, I was just starting to pull hair(s) out of my head over it.

So I’m now trying to understand the new bit of code you posted,

where did you get FileCount.Count() from, or is that a typo for xmlFileCount?

  • Joel

“jbrave” wrote:
Thanks for catching that typo, I was just starting to pull hair(s) out of my head over it.

So I’m now trying to understand the new bit of code you posted,

where did you get FileCount.Count() from, or is that a typo for xmlFileCount?

  • Joel
    If you look at section 10.17 in the BrightScriptReferenceManual.pdf, you’ll see that roXMLList implements the ifList interface, which is documented in section 10.1. Count() is a method of that interface.

So, you are checking:

xmlFileCount = xml.GetNamedElements(“file-count”)
’ create an roXMLLIst and assign the element file-count to that list (I don’t understand this enough to explain it to anyone myself)

If xmlFileCount <> invalid
’ check if xmlFileCount is null

And fileCount.Count() > 0
’ check if the array variable filecount contains at least one entry (why?)

Then

'assign the value of the field file-count
fileCount = xmlFileCount[ 0 ].GetText()

  • Joel

“jbrave” wrote:
xmlFileCount = xml.GetNamedElements(“file-count”)
’ create an roXMLLIst and assign the element file-count to that list (I don’t understand this enough to explain it to anyone myself)
Give me an roXMLList that contains every “file-count” element below whatever element “xml” references

“jbrave” wrote:
If xmlFileCount <> invalid
’ check if xmlFileCount is null
Correct.

“jbrave” wrote:
And fileCount.Count() > 0
’ check if the array variable filecount contains at least one entry (why?)
Basically, without testing it, I don’t know if GetNamedElements will return invalid or an empty roXMLList, so we check both, so the next line that tries to access the first element of the list doesn’t blow up if it’s the latter (an empty list)

“jbrave” wrote:
'assign the value of the field file-count
fileCount = xmlFileCount[ 0 ].GetText()
Correct.

Ok, cool. So if I understand it, if there is a bunch of xml like this:

sammy smith
10
steve jones
40

and I do this:

xmlFileCount = xml.GetNamedElements(“file-count”)

then I have an array with two entries, xmlFileCount[0] has a value of 10 and xmlFileCount[1] has a value of 40

Would that be an accurate assumption?

  • Joel

Almost. xmlFileCount is an roXMLList of roXMLElements, so xmlFileCount[0] is an roXMLElement whose GetText() method will return “10”.

So, xmlFileCount[0].GetText() is “10” and xmlFileCount[1].GetText() is “40”. If you need an integer you can either call:

intFileCount = Int(xmlFileCount[0].GetText()

Or

intFileCount = xmlFileCount[0].GetText().ToInt()

Both should return the same result, though unless you have absolute certainty that the XML file will always be correct, you’ll probably want to check to make sure GetText() actually returns a value first, to be safe.

Ok, that makes sense. I have one more question, I hope you don’t mind answering.

The reason I am getting the file-count variable was to dimension an array for each user with the number of files, each element of the array containing the URL to access each file. Now I realize what I need is a data structure like this:

[0] title, description, url
[1] title, description, url
[2] title, description, url

I think the roXMLList is the correct data structure to use, and perhaps all I need is to do something like this

xmlfileList=CreateObject(“roXMLElement”)
filelist=xmlFileList.Parse(xmlFileList)

and use the xml functions described in section 4.5:
fileTitle=FileList.user.title

Parse() actually returns a boolean that indicates whether the XML was correctly parsed, so you would reference xmlFileList as the root object instead of filelist. I think you probably want something more like this:

xmlfileList=CreateObject("roXMLElement")
If xmlFileList.Parse(xmlFileList) Then
    For Each user in xmlFileList.user
        fileTitle = user.title[x].GetText()
        fileURL = user.url[x].GetText()
        fileDescription = user.description[x].GetText()
        ' Do your user specific processing
    Next
End If

Assuming your XML is like this:

<users>
    <user>
        <title>MyTitle</title>
        <url>http://blah.blah</url>
        <description>blah blah blah</description>
    </user>
    <user>
        <title>MyTitle</title>
        <url>http://blah.blah</url>
        <description>blah blah blah</description>
    </user>
</users>

Yes, that is about the structure of the XML.

Well I tried implementing what you described in your previous posts, but I’m getting an error thrown, see asterisks in the code below:

/tmp/plugin/HGAAAAhOIGYV/pkg:/source/main.brs(85): runtime error ec: ‘Dot’ Operator attempted with invalid BrightScript Component or interface reference.

085: If xmlFileCount <> invalid And FileCountString.Count() > 0 Then

If I leave out all the testing and use this:

FileCountString=xml.GetNamedElements(“file-count”)[0].GetText()

it works just fine. The code:

xfer.setURL(api+resource+user+uresource+ckey)
xferResult = xfer.GetToString()
print “transfer-result”+xferResult

'ok, now we have the user info, we need the number of files that user has

if xml.Parse(xferResult)

'from user info get number of Files

xmlFileCount = xml.GetNamedElements(“file-count”)
****** If xmlFileCount <> invalid And FileCountString.Count() > 0 Then
FileCountString = xmlFileCount[0].GetText()
End If

print FileCountString
FileCountNumeric=val(FileCountString)
print FileCountNumeric
print type(FileCountNumeric)

end if

End Sub

In your If statement, you should be checking Count() on xmlFileCount, not on FileCountString.

If xmlFileCount <> invalid And xmlFileCount.Count() > 0 Then

Hate to abandon you, but it’s 4am here, and I’ve got a 5 year old’s party to go to in a few hours, so I need to hit the sack. Good luck!