Roku Developer Program

Join our online forum to talk to Roku developers and fellow channel creators. Ask questions, share tips with the community, and find helpful resources.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

XML Syntax for Deeper Category Levels

I am working with videoplayer from the SDK.

I would like to add additional levels of hierarchy in the categories. Right now, all I can seem to do is specify:

TOP LEVEL -> SUB-LEVEL -> CONTENT ITEMS

(where TOP LEVEL is the top "category", SUB-LEVEL is the "categoryLeaf" and CONTENT ITEMS are the items listed in the xml file referred to by the categoryLeaf.)

Is there a way to go deeper and wider, as in:

TOP LEVEL -> SUB-LEVEL1a -> SUB-LEVEL2 -> CONTENT ITEMS
----------- SUB-LEVEL1b -> SUB-LEVEL2 -> CONTENT ITEMS

Hopefully, you get what I mean.

Bruce Rothwell
0 Kudos
34 REPLIES 34
destruk
Binge Watcher

Re: XML Syntax for Deeper Category Levels

Yes you could do that. Or you could include your entire schema layout in a single XML file.
0 Kudos

Re: XML Syntax for Deeper Category Levels

Thank you destruk, for the reply.

I guess I wasn't specific in my question.... can you, or anyone else, show me at least one example on how to do it?

And, as a bonus, can anyone help with what the syntax is for other variations on schema? (I have not been able to find this in the SDK documentation).

Thanks!!

-
Bruce Rothwell
0 Kudos
destruk
Binge Watcher

Re: XML Syntax for Deeper Category Levels

I have created routines to read any kind of xml layout/schema I'd require for any channel I choose to create, but explaining how to do it is much more difficult.
Basically, for your top category xml you have that link to secondary category xml files. And those xml files point to other levels of files you want, and eventually you have a bottom content xml with the show/episode feed targets.
You can tell the two apart if you like by having your parser look for a heading you specifically create such as TargetType - xml would be another category list section, and anything else would be the end target like an mp4 or video or mp3.
To show off our work to other potential clients, we wanted to have a single application/channel that could show off every last feature Roku is capable of - all merged into a group of xml files, so we use the xml to set up the video feeds, mp3 files, video and audio playlists, gridscreens/poster screens, slideshows, single images, etc etc and it picks out what it needs for each feature section and creates the screen and different theming based entirely off the xml we feed into it. It can take months to make something like that, and whenever a new feature is added we expand it.
0 Kudos

Re: XML Syntax for Deeper Category Levels

Hi destruk,

I understand what you are saying... that you really cannot share any actual examples, because your XML files are the bread-n-butter of your business.

However, can you explain a little bit more about this bit?...

>You can tell the two apart if you like by having your parser look for a heading you specifically create such as TargetType - xml would be another category list section, and anything else would be the end target like an mp4 or video or mp3.

I am not understanding where in the code to find where look for headings (I'm new tho this arena).

Thx,
Bruce
0 Kudos
destruk
Binge Watcher

Re: XML Syntax for Deeper Category Levels

Categoryfeed.brs is where the parsing is for the main xml file, so we used that to check for extra headers/entries in the xml file it downloads.
conn.LoadCategoryFeed=load_category_feed ' this points the load routine to function load_category_feed so this is where you might want to look

A short example would be something like this generic code you should already have in that file:


Function load_category_feed(conn As Object) As Dynamic
http=NewHttp(conn.UrlCategoryFeed)
rsp=http.GetToStringWithRetry()
xml=CreateObject("roXMLElement")
If Not xml.Parse(rsp)
Print"Can't parse feed"
m.RoutineFailure=TRUE
Return invalid
End If

If islist(xml.entry)=FALSE
Print"invalid feed body"
Return invalid
End If
If xml.entry[0].GetName()<>"entry"
Print"no initial category tag"
Return invalid
End If
If xml.entry=invalid
Print"no categories tag"
Return invalid
End If

topNode=MakeEmptyCatNode()
topNode.Title="root"
topNode.isapphome=TRUE

categories=xml.GetChildElements()
Print"number of categories: "+itostr(categories.Count())
For Each e In categories
o=ParseCategoryNode(e) 'actual parsing happens here
If o<>invalid
topNode.AddKid(o)
Print"added new child node"
Else
Print"parse returned no child node"
End If
Next
Return topNode
End Function


'followed by this unique/modified code

Function ParseCategoryNode(xml As Object) As dynamic
o=init_category_item() 'setup defaults for an item
If xml.GetName()="entry"
o.TargetType=validstr(xml.targettype.GetText()) 'ADDED
o.TargetSource=validstr(xml.targetsource.GetText())
If o.TargetType="video"
'parse and read/import settings for a basic video file
o.Title=validstr(xml.Title.GetText()) 'Give the video icon a name to display on the screen
o.SDThumbmail=(xml.SDThumbnail.GetText()) 'give the submenu a thumbnail image for SD mode
o.HDThumbmail=(xml.SDThumbnail.GetText()) 'give the submenu a thumbnail image for HD mode
'for a single stream you'd just want a single entry for the media, for multiple streams parse with a loop for each media entry
o.Streamurls[0]=o.TargetSource
o.Bitrates[0]=strtoi(validstr(xml.Bitrate.GetText()))
o.StreamQualities[0]=validstr(xml.StreamQuality.GetText())
End If
If TargetType="submenu"
'parse and read/import settings for a submenu
o.SDThumbmail=validstr(xml.SDThumbnail.GetText()) 'give the submenu a thumbnail image for SD mode
o.HDThumbmail=validstr(xml.SDThumbnail.GetText()) 'give the submenu a thumbnail image for HD mode
o.Feed=o.TargetSource 'set up URL for submenu's XML file
o.Title=validstr(xml.Title.GetText()) 'Give the submenu icon a name to display on the screen
End If
End If
Return o
End Function


Then for displaying your screen you need to query the TargetType value of the item that was selected - if it's a "submenu" then have it create another poster screen and read out the next URL for the new screen's xml content, if it's a "video" then throw the selection information to the video player routine.

Something like that would do what you needed it to do with an xml like this:


<?xml version="1.0" encoding="UTF-8" ?>
<categories>
<entry>
<TargetType>submenu</TargetType>
<Title>My Submenu</Title>
<SDThumbnail>http://myserver.com/images/submenusd.png</SDThumbnail>
<HDThumbnail>http://myserver.com/images/submenuhd.png</HDThumbnail>
<TargetSource>http://myserver.com/xml/submenu.xml</TargetSource>
</entry>

<entry>
<TargetType>video</TargetType>
<Title>My Video</Title>
<SDThumbnail>http://myserver.com/images/myvideosd.png</SDThumbnail>
<HDThumbnail>http://myserver.com/images/myvideohd.png</HDThumbnail>
<TargetSource>http://myserver.com/content/myvideo.mp4</TargetSource>
<Bitrate>1000</Bitrate>
<StreamQuality>SD</StreamQuality>
</entry>

<entry>
<TargetType>submenu</TargetType>
<Title>More Videos</Title>
<SDThumbnail>http://myserver.com/images/morevideossd.png</SDThumbnail>
<HDThumbnail>http://myserver.com/images/morevideoshd.png</HDThumbnail>
<TargetSource>http://myserver.com/xml/morevideos.xml</TargetSource>
</entry>
</categories>


You'll need to modify the channel script to work for your particular needs. You can have more than one xml parsing routine - the videoplayer example has one for the categories and a separate one for the shows (showfeed.brs).
0 Kudos
claudioc
Visitor

Re: XML Syntax for Deeper Category Levels

i just wanted to add, a big thanks for this example man, im going to mess around with it now, this was a serious problem for me, i was considering making 2 versions of a channel because the content requirements were too rich and deep for the 3 level menus, so you seriously helped me out big time. This part of the documentation is lacking a bit, its a harder language to learn (brightscript) since its a combination of a # of things and not having a variety of information on these said languages makes the references alone sort of moot. but in any event thanks very much i know you wrote this back in september, but the truth is man you helping others even though you do this for a living is really cool. most of us just want something for our private use and so on. and your details wont effect your business in a negative way, take a look around man theres so many ads requesting a roku developer, and barely anyone ever hits these people up, so your good.

Claudio
0 Kudos
destruk
Binge Watcher

Re: XML Syntax for Deeper Category Levels

You're welcome. Most of the professional channel developers I know, would want to help, but usually the Roku support team jumps in before anyone else sees the thread. 🙂
0 Kudos
claudioc
Visitor

Re: XML Syntax for Deeper Category Levels

hey i got a question actually, i tried to add the code u suggested following the spot you mentioned but when i send the source code over to the roku the channel no longer shows, and i made sure my old version would work correctly, so im thinking i broke something in the code, i used your example of what "should already be there" since mine was just a bit different, keep in mind im using a Roku 2 XS heres the way my categoryFeed.brs file looks, can you tell me what i did wrong, so that i can get the channel to show up, i changed NOTHING else other than what you suggested exactly:

categoryFeed.brs:



'******************************************************
'** Video Player Example Application -- Category Feed
'** November 2009
'** Copyright (c) 2009 Roku Inc. All Rights Reserved.
'******************************************************

'******************************************************
' Set up the category feed connection object
' This feed provides details about top level categories
'******************************************************
Function InitCategoryFeedConnection() As Object

conn = CreateObject("roAssociativeArray")

conn.UrlPrefix = "mywebsitegoeshere.com/xml"
conn.UrlCategoryFeed = conn.UrlPrefix + "/categories.xml"

conn.Timer = CreateObject("roTimespan")

conn.LoadCategoryFeed = load_category_feed
conn.GetCategoryNames = get_category_names

print "created feed connection for " + conn.UrlCategoryFeed
return conn

End Function

'*********************************************************
'** Create an array of names representing the children
'** for the current list of categories. This is useful
'** for filling in the filter banner with the names of
'** all the categories at the next level in the hierarchy
'*********************************************************
Function get_category_names(categories As Object) As Dynamic

categoryNames = CreateObject("roArray", 100, true)

for each category in categories.kids
'print category.Title
categoryNames.Push(category.Title)
next

return categoryNames

End Function


'******************************************************************
'** Given a connection object for a category feed, fetch,
'** parse and build the tree for the feed. the results are
'** stored hierarchically with parent/child relationships
'** with a single default node named Root at the root of the tree
'******************************************************************
Function load_category_feed(conn As Object) As Dynamic
http=NewHttp(conn.UrlCategoryFeed)
rsp=http.GetToStringWithRetry()
xml=CreateObject("roXMLElement")
If Not xml.Parse(rsp)
Print"Can't parse feed"
m.RoutineFailure=TRUE
Return invalid
End If

If islist(xml.entry)=FALSE
Print"invalid feed body"
Return invalid
End If
If xml.entry[0].GetName()<>"entry"
Print"no initial category tag"
Return invalid
End If
If xml.entry=invalid
Print"no categories tag"
Return invalid
End If

topNode=MakeEmptyCatNode()
topNode.Title="root"
topNode.isapphome=TRUE

categories=xml.GetChildElements()
Print"number of categories: "+itostr(categories.Count())
For Each e In categories
o=ParseCategoryNode(e) 'actual parsing happens here
If o<>invalid
topNode.AddKid(o)
Print"added new child node"
Else
Print"parse returned no child node"
End If
Next
Return topNode
End Function

'******************************************************
'This Section Enables Multiple Tiers of Levels
'******************************************************

Function ParseCategoryNode(xml As Object) As dynamic
o=init_category_item() 'setup defaults for an item
If xml.GetName()="entry"
o.TargetType=validstr(xml.targettype.GetText()) 'ADDED
o.TargetSource=validstr(xml.targetsource.GetText())
If o.TargetType="video"
'parse and read/import settings for a basic video file
o.Title=validstr(xml.Title.GetText()) 'Give the video icon a name to display on the screen
o.SDThumbmail=(xml.SDThumbnail.GetText()) 'give the submenu a thumbnail image for SD mode
o.HDThumbmail=(xml.SDThumbnail.GetText()) 'give the submenu a thumbnail image for HD mode
'for a single stream you'd just want a single entry for the media, for multiple streams parse with a loop for each media entry
o.Streamurls[0]=o.TargetSource
o.Bitrates[0]=strtoi(validstr(xml.Bitrate.GetText()))
o.StreamQualities[0]=validstr(xml.StreamQuality.GetText())
End If
If TargetType="submenu"
'parse and read/import settings for a submenu
o.SDThumbmail=validstr(xml.SDThumbnail.GetText()) 'give the submenu a thumbnail image for SD mode
o.HDThumbmail=validstr(xml.SDThumbnail.GetText()) 'give the submenu a thumbnail image for HD mode
o.Feed=o.TargetSource 'set up URL for submenu's XML file
o.Title=validstr(xml.Title.GetText()) 'Give the submenu icon a name to display on the screen
End If
End If
Return o
End Function

'******************************************************
'MakeEmptyCatNode - use to create top node in the tree
'******************************************************
Function MakeEmptyCatNode() As Object
return init_category_item()
End Function


'***********************************************************
'Given the xml element to an <Category> tag in the category
'feed, walk it and return the top level node to its tree
'***********************************************************
Function ParseCategoryNode(xml As Object) As dynamic
o = init_category_item()

print "ParseCategoryNode: " + xml.GetName()
'PrintXML(xml, 5)

'parse the curent node to determine the type. everything except
'special categories are considered normal, others have unique types
if xml.GetName() = "category" then
print "category: " + xml@title + " | " + xml@description
o.Type = "normal"
o.Title = xml@title
o.Description = xml@Description
o.ShortDescriptionLine1 = xml@Title
o.ShortDescriptionLine2 = xml@Description
o.SDPosterURL = xml@sd_img
o.HDPosterURL = xml@hd_img
elseif xml.GetName() = "categoryLeaf" then
o.Type = "normal"
elseif xml.GetName() = "specialCategory" then
if invalid <> xml.GetAttributes() then
for each a in xml.GetAttributes()
if a = "type" then
o.Type = xml.GetAttributes()[a]
print "specialCategory: " + xml@type + "|" + xml@title + " | " + xml@description
o.Title = xml@title
o.Description = xml@Description
o.ShortDescriptionLine1 = xml@Title
o.ShortDescriptionLine2 = xml@Description
o.SDPosterURL = xml@sd_img
o.HDPosterURL = xml@hd_img
endif
next
endif
else
print "ParseCategoryNode skip: " + xml.GetName()
return invalid
endif

'only continue processing if we are dealing with a known type
'if new types are supported, make sure to add them to the list
'and parse them correctly further downstream in the parser
while true
if o.Type = "normal" exit while
if o.Type = "special_category" exit while
print "ParseCategoryNode unrecognized feed type"
return invalid
end while

'get the list of child nodes and recursed
'through everything under the current node
for each e in xml.GetBody()
name = e.GetName()
if name = "category" then
print "category: " + e@title + " [" + e@description + "]"
kid = ParseCategoryNode(e)
kid.Title = e@title
kid.Description = e@Description
kid.ShortDescriptionLine1 = xml@Description
kid.SDPosterURL = xml@sd_img
kid.HDPosterURL = xml@hd_img
o.AddKid(kid)
elseif name = "categoryLeaf" then
print "categoryLeaf: " + e@title + " [" + e@description + "]"
kid = ParseCategoryNode(e)
kid.Title = e@title
kid.Description = e@Description
kid.Feed = e@feed
o.AddKid(kid)
elseif name = "specialCategory" then
print "specialCategory: " + e@title + " [" + e@description + "]"
kid = ParseCategoryNode(e)
kid.Title = e@title
kid.Description = e@Description
kid.sd_img = e@sd_img
kid.hd_img = e@hd_img
kid.Feed = e@feed
o.AddKid(kid)
endif
next

return o
End Function


'******************************************************
'Initialize a Category Item
'******************************************************
Function init_category_item() As Object
o = CreateObject("roAssociativeArray")
o.Title = ""
o.Type = "normal"
o.Description = ""
o.Kids = CreateObject("roArray", 100, true)
o.Parent = invalid
o.Feed = ""
o.IsLeaf = cn_is_leaf
o.AddKid = cn_add_kid
return o
End Function


'********************************************************
'** Helper function for each node, returns true/false
'** indicating that this node is a leaf node in the tree
'********************************************************
Function cn_is_leaf() As Boolean
if m.Kids.Count() > 0 return true
if m.Feed <> "" return false
return true
End Function


'*********************************************************
'** Helper function for each node in the tree to add a
'** new node as a child to this node.
'*********************************************************
Sub cn_add_kid(kid As Object)
if kid = invalid then
print "skipping: attempt to add invalid kid failed"
return
endif

kid.Parent = m
m.Kids.Push(kid)
End Sub


and just to mention it i used your xml syntax you clearly showed us how to add so we could do submenu or video, that part i believe couldnt be more clear so thank you there, but since the *.brs file seems to be not working correctly, and im not sure how to debug it honestly, i would love to know what i did wrong, so i could get the submenus working. also was i suppose to modify anything in the appmain.brs ? or anything else for that matter to accomplish what you explained, thank you very much for following up man i appreciate it very much, im working tirelessly to try and get this project finished, and i got all the art made, and video made and im just left with fixing the submenu levels and i can finish up. and i do realize mywebsitegoeshere.com is not correct i just shielded my website details. and in closing ALL im after changing from the videoplayer example is just having submenus like you explained, so i just need the code to work for that only.

Claudio
0 Kudos
claudioc
Visitor

Re: XML Syntax for Deeper Category Levels

well.. i figured out the debugger, and found an error, heres the problem man, i had the same syntax written twice:

Function ParseCategoryNode(xml As Object) As dynamic

so what i tried to do, was combine it like the following with the previously used command:


Function ParseCategoryNode(xml As Object) As dynamic
o = init_category_item()

print "ParseCategoryNode: " + xml.GetName()
'PrintXML(xml, 5)

'parse the curent node to determine the type. everything except
'special categories are considered normal, others have unique types
if xml.GetName() = "category" then
print "category: " + xml@title + " | " + xml@description
o.Type = "normal"
o.Title = xml@title
o.Description = xml@Description
o.ShortDescriptionLine1 = xml@Title
o.ShortDescriptionLine2 = xml@Description
o.SDPosterURL = xml@sd_img
o.HDPosterURL = xml@hd_img
elseif xml.GetName() = "categoryLeaf" then
o.Type = "normal"
elseif xml.GetName() = "specialCategory" then
if invalid <> xml.GetAttributes() then
for each a in xml.GetAttributes()
if a = "type" then
o.Type = xml.GetAttributes()[a]
print "specialCategory: " + xml@type + "|" + xml@title + " | " + xml@description
o.Title = xml@title
o.Description = xml@Description
o.ShortDescriptionLine1 = xml@Title
o.ShortDescriptionLine2 = xml@Description
o.SDPosterURL = xml@sd_img
o.HDPosterURL = xml@hd_img
endif
next
endif
else
print "ParseCategoryNode skip: " + xml.GetName()
return invalid
endif

'only continue processing if we are dealing with a known type
'if new types are supported, make sure to add them to the list
'and parse them correctly further downstream in the parser
while true
if o.Type = "normal" exit while
if o.Type = "special_category" exit while
print "ParseCategoryNode unrecognized feed type"
return invalid
end while

'get the list of child nodes and recursed
'through everything under the current node
for each e in xml.GetBody()
name = e.GetName()
if name = "category" then
print "category: " + e@title + " [" + e@description + "]"
kid = ParseCategoryNode(e)
kid.Title = e@title
kid.Description = e@Description
kid.ShortDescriptionLine1 = xml@Description
kid.SDPosterURL = xml@sd_img
kid.HDPosterURL = xml@hd_img
o.AddKid(kid)
elseif name = "categoryLeaf" then
print "categoryLeaf: " + e@title + " [" + e@description + "]"
kid = ParseCategoryNode(e)
kid.Title = e@title
kid.Description = e@Description
kid.Feed = e@feed
o.AddKid(kid)
elseif name = "specialCategory" then
print "specialCategory: " + e@title + " [" + e@description + "]"
kid = ParseCategoryNode(e)
kid.Title = e@title
kid.Description = e@Description
kid.sd_img = e@sd_img
kid.hd_img = e@hd_img
kid.Feed = e@feed
o.AddKid(kid)
endif
next

return o

o=init_category_item() 'setup defaults for an item
If xml.GetName()="entry"
o.TargetType=validstr(xml.targettype.GetText()) 'ADDED
o.TargetSource=validstr(xml.targetsource.GetText())
If o.TargetType="video"
'parse and read/import settings for a basic video file
o.Title=validstr(xml.Title.GetText()) 'Give the video icon a name to display on the screen
o.SDThumbmail=(xml.SDThumbnail.GetText()) 'give the submenu a thumbnail image for SD mode
o.HDThumbmail=(xml.SDThumbnail.GetText()) 'give the submenu a thumbnail image for HD mode
'for a single stream you'd just want a single entry for the media, for multiple streams parse with a loop for each media entry
o.Streamurls[0]=o.TargetSource
o.Bitrates[0]=strtoi(validstr(xml.Bitrate.GetText()))
o.StreamQualities[0]=validstr(xml.StreamQuality.GetText())
End If
If TargetType="submenu"
'parse and read/import settings for a submenu
o.SDThumbmail=validstr(xml.SDThumbnail.GetText()) 'give the submenu a thumbnail image for SD mode
o.HDThumbmail=validstr(xml.SDThumbnail.GetText()) 'give the submenu a thumbnail image for HD mode
o.Feed=o.TargetSource 'set up URL for submenu's XML file
o.Title=validstr(xml.Title.GetText()) 'Give the submenu icon a name to display on the screen
End If
End If
Return o
End Function


and i tried your other code in place of what was already there as you first mentioned, but it returns errors so i left my original and tested that, plus commented out the 5 lines with ' since it was just a command if something failed to work so i figured worth commenting out to test. In any event, no matter what i do, the new commands for submenu and video target type and such, the xml files just wont parse because its missing the <feed></feed> but obviously thats not how you explained to use the xml so im confused bud. here is my entire *.brs file as i have it now besides the specific part i showed you just so i could explain what i did to implement what you showed me:



'******************************************************
'** Video Player Example Application -- Category Feed
'** November 2009
'** Copyright (c) 2009 Roku Inc. All Rights Reserved.
'******************************************************

'******************************************************
' Set up the category feed connection object
' This feed provides details about top level categories
'******************************************************
Function InitCategoryFeedConnection() As Object

conn = CreateObject("roAssociativeArray")

conn.UrlPrefix = "you-might-get.strangled.net/xml"
conn.UrlCategoryFeed = conn.UrlPrefix + "/categories.xml"

conn.Timer = CreateObject("roTimespan")

conn.LoadCategoryFeed = load_category_feed
conn.GetCategoryNames = get_category_names

print "created feed connection for " + conn.UrlCategoryFeed
return conn

End Function

'*********************************************************
'** Create an array of names representing the children
'** for the current list of categories. This is useful
'** for filling in the filter banner with the names of
'** all the categories at the next level in the hierarchy
'*********************************************************
Function get_category_names(categories As Object) As Dynamic

categoryNames = CreateObject("roArray", 100, true)

for each category in categories.kids
'print category.Title
categoryNames.Push(category.Title)
next

return categoryNames

End Function


'******************************************************************
'** Given a connection object for a category feed, fetch,
'** parse and build the tree for the feed. the results are
'** stored hierarchically with parent/child relationships
'** with a single default node named Root at the root of the tree
'******************************************************************
Function load_category_feed(conn As Object) As Dynamic

http = NewHttp(conn.UrlCategoryFeed)

Dbg("url: ", http.Http.GetUrl())

m.Timer.Mark()
rsp = http.GetToStringWithRetry()
Dbg("Took: ", m.Timer)

m.Timer.Mark()
xml=CreateObject("roXMLElement")
if not xml.Parse(rsp) then
print "Can't parse feed"
return invalid
endif
Dbg("Parse Took: ", m.Timer)

m.Timer.Mark()
if xml.category = invalid then
print "no categories tag"
return invalid
endif

if islist(xml.category) = false then
print "invalid feed body"
return invalid
endif

if xml.category[0].GetName() <> "category" then
print "no initial category tag"
return invalid
endif

topNode = MakeEmptyCatNode()
topNode.Title = "root"
topNode.isapphome = true

print "begin category node parsing"

categories = xml.GetChildElements()
print "number of categories: " + itostr(categories.Count())
for each e in categories
o = ParseCategoryNode(e)
if o <> invalid then
topNode.AddKid(o)
print "added new child node"
else
print "parse returned no child node"
endif
next
Dbg("Traversing: ", m.Timer)

return topNode

End Function

'******************************************************
'MakeEmptyCatNode - use to create top node in the tree
'******************************************************
Function MakeEmptyCatNode() As Object
return init_category_item()
End Function


'***********************************************************
'Given the xml element to an <Category> tag in the category
'feed, walk it and return the top level node to its tree
'***********************************************************
Function ParseCategoryNode(xml As Object) As dynamic
o = init_category_item()

print "ParseCategoryNode: " + xml.GetName()
'PrintXML(xml, 5)

'parse the curent node to determine the type. everything except
'special categories are considered normal, others have unique types
if xml.GetName() = "category" then
print "category: " + xml@title + " | " + xml@description
o.Type = "normal"
o.Title = xml@title
o.Description = xml@Description
o.ShortDescriptionLine1 = xml@Title
o.ShortDescriptionLine2 = xml@Description
o.SDPosterURL = xml@sd_img
o.HDPosterURL = xml@hd_img
elseif xml.GetName() = "categoryLeaf" then
o.Type = "normal"
elseif xml.GetName() = "specialCategory" then
if invalid <> xml.GetAttributes() then
for each a in xml.GetAttributes()
if a = "type" then
o.Type = xml.GetAttributes()[a]
print "specialCategory: " + xml@type + "|" + xml@title + " | " + xml@description
o.Title = xml@title
o.Description = xml@Description
o.ShortDescriptionLine1 = xml@Title
o.ShortDescriptionLine2 = xml@Description
o.SDPosterURL = xml@sd_img
o.HDPosterURL = xml@hd_img
endif
next
endif
else
print "ParseCategoryNode skip: " + xml.GetName()
return invalid
endif

'only continue processing if we are dealing with a known type
'if new types are supported, make sure to add them to the list
'and parse them correctly further downstream in the parser
while true
if o.Type = "normal" exit while
if o.Type = "special_category" exit while
print "ParseCategoryNode unrecognized feed type"
return invalid
end while

'get the list of child nodes and recursed
'through everything under the current node
for each e in xml.GetBody()
name = e.GetName()
if name = "category" then
print "category: " + e@title + " [" + e@description + "]"
kid = ParseCategoryNode(e)
kid.Title = e@title
kid.Description = e@Description
kid.ShortDescriptionLine1 = xml@Description
kid.SDPosterURL = xml@sd_img
kid.HDPosterURL = xml@hd_img
o.AddKid(kid)
elseif name = "categoryLeaf" then
print "categoryLeaf: " + e@title + " [" + e@description + "]"
kid = ParseCategoryNode(e)
kid.Title = e@title
kid.Description = e@Description
kid.Feed = e@feed
o.AddKid(kid)
elseif name = "specialCategory" then
print "specialCategory: " + e@title + " [" + e@description + "]"
kid = ParseCategoryNode(e)
kid.Title = e@title
kid.Description = e@Description
kid.sd_img = e@sd_img
kid.hd_img = e@hd_img
kid.Feed = e@feed
o.AddKid(kid)
endif
next

return o

o=init_category_item() 'setup defaults for an item
If xml.GetName()="entry"
o.TargetType=validstr(xml.targettype.GetText()) 'ADDED
o.TargetSource=validstr(xml.targetsource.GetText())
If o.TargetType="video"
'parse and read/import settings for a basic video file
o.Title=validstr(xml.Title.GetText()) 'Give the video icon a name to display on the screen
o.SDThumbmail=(xml.SDThumbnail.GetText()) 'give the submenu a thumbnail image for SD mode
o.HDThumbmail=(xml.SDThumbnail.GetText()) 'give the submenu a thumbnail image for HD mode
'for a single stream you'd just want a single entry for the media, for multiple streams parse with a loop for each media entry
o.Streamurls[0]=o.TargetSource
o.Bitrates[0]=strtoi(validstr(xml.Bitrate.GetText()))
o.StreamQualities[0]=validstr(xml.StreamQuality.GetText())
End If
If TargetType="submenu"
'parse and read/import settings for a submenu
o.SDThumbmail=validstr(xml.SDThumbnail.GetText()) 'give the submenu a thumbnail image for SD mode
o.HDThumbmail=validstr(xml.SDThumbnail.GetText()) 'give the submenu a thumbnail image for HD mode
o.Feed=o.TargetSource 'set up URL for submenu's XML file
o.Title=validstr(xml.Title.GetText()) 'Give the submenu icon a name to display on the screen
End If
End If
Return o
End Function


'******************************************************
'Initialize a Category Item
'******************************************************
Function init_category_item() As Object
o = CreateObject("roAssociativeArray")
o.Title = ""
o.Type = "normal"
o.Description = ""
o.Kids = CreateObject("roArray", 100, true)
o.Parent = invalid
o.Feed = ""
o.IsLeaf = cn_is_leaf
o.AddKid = cn_add_kid
return o
End Function


'********************************************************
'** Helper function for each node, returns true/false
'** indicating that this node is a leaf node in the tree
'********************************************************
Function cn_is_leaf() As Boolean
if m.Kids.Count() > 0 return true
if m.Feed <> "" return false
return true
End Function


'*********************************************************
'** Helper function for each node in the tree to add a
'** new node as a child to this node.
'*********************************************************
Sub cn_add_kid(kid As Object)
if kid = invalid then
print "skipping: attempt to add invalid kid failed"
return
endif

kid.Parent = m
m.Kids.Push(kid)
End Sub


I hope you can shed some light on my mistake here. i feel like considering the directions initially given didnt really say you will have a command like this already in your example, so you need to combine with that already used function in some way, i did my best to wing it and try and combine it with that function, and i get no actual errors when viewing the debug screen so i assume that part is ok.. so perhaps something is needed on the ShowFeed.brs or something but i been at this for like 8 hours straight and im getting no where unfortunately. so ill wait for a response 😆

Claudio
0 Kudos