Reading xml?
Monkey Forums/Monkey Programming/Reading xml?
| ||
Hi all. I'm currently using the skn3/config example to read my level data from an xml file, but have a question regarding reading some of the values The xml data is from a .tmx (tiled) file <map version="1.0" orientation="orthogonal" width="80" height="30" tilewidth="10" tileheight="10"> <tileset firstgid="1" name="mytiles" tilewidth="10" tileheight="10"> <image source="tileset.png" width="80" height="640"/> </tileset> <layer name="Level" width="80" height="30"> <data encoding="csv"> .....some data </data> </layer> <objectgroup name="Object Layer 1" width="80" height="30"> <object name="Button" type="dButton" x="540" y="270" width="10" height="10"> <properties> <property name="Number" value="1"/> </properties> </object> </objectgroup> </map> I'm currently reading the data like this-- nodes = c1.FindNodesByPath("map/objectgroup/object") For Local node := Eachin nodes Select node.GetAttribute("name") Case "Button" If node.GetAttribute("type")="dButton" Then 'Door button DoorBX[NumDoorButtons]=Int(node.GetAttribute("x")) DoorBY[NumDoorButtons]=Int(node.GetAttribute("y")) NumDoorButtons = NumDoorButtons + 1 End End Select Next yes, I know I shouldn't really be using arrays for holding the data, but still... How do I go about reading the "Number" property for the object type "bDutton"? Thanks. :) |
| ||
Eeuw, XML! Eeeeuuww!!! I think you've over complicate it by adding multiple parameters in each line. The last time I tried anything with XML I kept everything seperate.. <object> <name>Giant Long Thing with Tentacles</name> <width>128</width> <height>64</height> </object> Since you're having to code the parser, it just seems easier to format the data in a way that's more readable. .. To be honest, I prefer the .ini format, myself. [Object] Name=Giant Long Thing with Tentacles Width=128 Height=64 Then you can simply use Monkey's Split function to split up each line where the = is, and easily access each parameter. ... But that's just me!! |
| ||
I was hoping not to have to create my own level format and just use something already available. A .tmx file is perfect(ish) as I can just keep the saved file directly from tiled. |
| ||
My answer is quick, simple, and kinda dirty. .. but I imagine you expected as much.. I wrote a quick and dirty SeekXML function. Method SeekXML$(ftxt$,fseek$) Local ff,fa,fb,fn,ftmp$,ftxtUpper$=ftxt.ToUpper() fseek=" "+fseek.ToUpper()+"=" ff=ftxtUpper.FindLast(fseek) If ff>-1 fa=ftxt.Find(ftmp.FromChar(34),ff+1) fb=ftxt.Find(ftmp.FromChar(34),fa+1) If fa>-1 And fb>-1 For fn=fa+1 To fb-1 ftmp=ftmp+ftxt.FromChar(ftxt[fn]) Next Endif Return ftmp Endif If ff=-1 Then Return "-=-" End Method Feel free to bombard me with "You could've done it XYZ way!!" complaints, people.. Usage.. I'm assuming you can gain access to each individual line of XML. If not.. umm.. urrr.. You're buggered!! Local txt$ Local c1$="<object name="+txt.FromChar(34)+"Button"+txt.FromChar(34)+" type="+txt.FromChar(34)+"dButton"+txt.FromChar(34)+" x="+txt.FromChar(34)+"540"+txt.FromChar(34)+" y="+txt.FromChar(34)+"270"+txt.FromChar(34)+" width="+txt.FromChar(34)+"10"+txt.FromChar(34)+" height="+txt.FromChar(34)+"10"+txt.FromChar(34)+">" Text 100,80,SeekXML(c1,"Name") Text 100,100,SeekXML(c1,"X") Text 100,120,SeekXML(c1,"Y") Text 100,140,SeekXML(c1,"Width") Text 100,160,SeekXML(c1,"Height") Text 100,180,SeekXML(c1,"Pants") c1="<objectgroup name="+txt.FromChar(34)+"Object Layer 1"+txt.FromChar(34)+" width="+txt.FromChar(34)+"80"+txt.FromChar(34)+" height="+txt.FromChar(34)+"30"+txt.FromChar(34)+">" Text 200,80,SeekXML(c1,"Name") Text 200,100,SeekXML(c1,"X") Text 200,120,SeekXML(c1,"Y") Text 200,140,SeekXML(c1,"Width") Text 200,160,SeekXML(c1,"Height") Text 200,180,SeekXML(c1,"Pants") |
| ||
unfortunately I can do that with the current functions - nodes = c1.FindNodesByPath("map/objectgroup/object/properties/property") will give me the information for all of the properties, however, what I want doesn't seem to be a function - reading ONLY the property tag that falls within the CURRENT node. I would like OtherData[NumDoorButtons] to grab the property value from the current "Button", not a list of all properties that I can't relate in any way back to the data that I am trying to connect it to. nodes = c1.FindNodesByPath("map/objectgroup/object") For Local node := Eachin nodes Select node.GetAttribute("name") Case "Button" If node.GetAttribute("type")="dButton" Then 'Door button DoorBX[NumDoorButtons]=Int(node.GetAttribute("x")) DoorBY[NumDoorButtons]=Int(node.GetAttribute("y")) OtherData[NumDoorButtons] = value from property with name="Number" within CURRENT object with name="Button" NumDoorButtons = NumDoorButtons + 1 End End Select Next |
| ||
you mean this?local nn:XMLNode = node.GetChild("properties").GetChild("property") if nn.GetAttribute("name")="Number" Then OtherData[NumDoorButtons] = nn.GetAttribute("value") if your current node is "object" you still need to get the child. if you have a lot of properties, you'll have to set "nn" to a List<XMLNode> and "GetDescendents" ...or while/Wend through using nn.GetNextSibling("property"). |
| ||
I tried switching to xml.monkey instead of config.monkey, however I can seem to read anything at all from my xml file :( level01.xml <?xml version="1.0" encoding="UTF-8"?> <map version="1.0" orientation="orthogonal" width="80" height="30" tilewidth="10" tileheight="10"> <tileset firstgid="1" name="mytiles" tilewidth="10" tileheight="10"> <image source="tileset.png" width="80" height="640"/> </tileset> <layer name="Level" width="80" height="30"> <data encoding="csv"> 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,80,201,202,202,203,79,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,209,210,210,211,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,209,210,210,211,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,209,210,210,211,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,209,210,227,211,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,80,201, 0,0,0,0,0,0,209,210,210,211,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,209, 0,0,0,0,0,0,209,210,210,211,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,209, 0,0,0,0,0,0,209,210,210,211,138,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,209, 0,0,0,0,0,0,209,210,210,211,46,47,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,209, 0,0,0,0,0,0,209,210,210,211,71,55,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,209, 0,0,0,0,0,0,209,210,210,211,142,139,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,209, 0,0,0,0,0,0,209,235,210,211,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,209, 0,0,0,0,0,0,209,210,210,211,0,69,70,0,0,0,0,69,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,209, 0,0,0,0,0,0,209,210,210,211,138,140,141,0,0,0,0,140,141,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,41,42,43,44,46,47,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,209, 0,0,0,0,0,0,209,210,210,211,0,0,0,0,0,0,0,0,0,0,0,0,0,41,42,43,44,46,47,0,0,0,0,0,0,0,0,0,0,0,76,77,49,70,51,52,71,55,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,209, 0,0,0,0,0,0,217,218,218,219,0,0,0,0,0,0,0,0,0,0,0,76,77,49,70,51,52,71,55,0,0,0,0,0,0,0,0,0,0,80,204,205,249,141,138,138,140,251,202,203,79,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,209, 0,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,0,0,0,0,80,204,205,249,141,138,138,140,251,202,203,79,0,0,0,0,0,0,0,0,0,83,0,0,0,0,0,217,218,219,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,80,201,202,202,202,202,202,202,202,202,202,202,202,221, 0,0,0,0,0,0,0,0,86,0,0,0,0,0,0,0,0,0,92,93,0,0,83,0,0,0,0,0,217,218,219,0,0,0,0,0,0,0,0,0,0,85,0,0,0,0,0,0,86,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,209,212,218,218,218,218,218,218,218,218,218,213,210, 0,0,0,0,0,0,0,0,0,0,0,0,80,204,205,206,79,0,100,101,0,0,85,0,0,0,0,0,0,86,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,217,219,0,0,0,0,0,0,0,0,0,209,210, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,85,0,0,0,108,109,0,0,0,0,0,0,0,0,0,0,0,0,0,80,89,90,91,79,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,209,210, 0,0,0,0,73,74,75,0,0,0,0,0,0,0,0,0,0,0,116,117,0,76,77,0,0,175,176,0,73,74,75,76,77,0,97,227,99,0,0,0,0,0,0,0,0,0,0,0,0,0,73,74,75,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,209,210, 201,203,79,80,201,242,242,202,202,202,202,202,202,202,202,202,202,202,202,202,202,242,242,202,202,207,208,202,242,242,242,202,202,202,241,241,241,202,202,202,202,202,202,202,202,202,202,202,202,202,242,242,242,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,221,210, 209,211,169,169,209,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210 </data> </layer> <objectgroup name="Object Layer 1" width="80" height="30"> <object name="Start" x="190" y="280"/> <object name="Door" type="Door" x="670" y="260" width="10" height="20"> <properties> <property name="Number" value="1"/> </properties> </object> <object name="Door" type="Door" x="570" y="270" width="10" height="10"> <properties> <property name="Number" value="2"/> </properties> </object> <object name="Door" type="Door" x="610" y="260" width="10" height="10"> <properties> <property name="Number" value="3"/> </properties> </object> <object name="Button" type="dButton" x="540" y="270" width="10" height="10"> <properties> <property name="Number" value="1"/> </properties> </object> </objectgroup> </map> 'load xml Local err:XMLError Local xml:= ParseXML(LoadString("level01.xml"), err) If xml = Null Error("doh!") If err <> Null Then Print err 'parse xml Local sheet:= xml.GetChild("map").GetChild("objectgroup") Print "name = '"+sheet.GetAttribute("name")+"'" Have I missed something important? |
| ||
Nobody? |
| ||
Looks like its time for me to look into writing another Tiled reader/writer but this round in Monkey. Sure, Diddy has it builtin, but I like to create my own stuff :) I'll look into this some more, as I haven't had much exposure with Monkey yet. I'll focus on XML as my entry point into Monkey and I'll get back with you on this. I wrote a Tiled TMX Reader/Writer for BlitzMax, C#, REALbasic (now Xojo), and Java. What's ONE more? :) I'll keep you posted as how to handle reading the XML. Generally, there is a GetAttrib or GetAttribute in the XML parser you are using that allows you to get the attributes. Some even break it down into Nodes, where there is a Parent Node and Child Node(s). You iterate through the Parents nodes until you reach the child nodes, and then grab the attributes accordingly.... I'll need to see how Monkey does this myself, but is shouldn't be that complicated. EDIT: It just occured to me that you are using skn3's module to handle XML parsing. I just looked at it, and seems to be pretty straight forward. I'll have a look at it tonight. I like the idea that its all in one source. I'd love to have the writer class to go with it too :) Guess I'll add that to my TODO list too! |
| ||
Psst take a look here for a more comprehensive XML module: http://www.monkeycoder.co.nz/Community/posts.php?topic=4125 There should be examples to cover everything you want to know. That config module is pretty ancient now and very slow compared to the one above and one that comes with diddy. [Edit] Whoops seems you did switch already. Well your code is failing because the doc node is always treated as your root node. So you don't need to bother with GetChild("map") |
| ||
Skn3: Thats the page I've been looking at. I'm *just* now sitting down to have a go at your implementation of XML parsing. I didn't really have a deep look at it earlier, but I now see that it parses and creates XML. :) Very cool. Thanks for that module too. Looking forward to seeing what I can do using it :) |
| ||
Computercoder, I'd love to see your Tiled importer working. I'm trying to import a map by myself, but my code sucks :( |
| ||
RENGAC, I've been busy with getting the OUYA controllers working over here with Ignition, but I'll be soon able to get this going. Perhaps in a couple days I could have the reader ready :) |
| ||
Nice! |
| ||
Computercoder, I'd love to see your Tiled importer working. I'm trying to import a map by myself, but my code sucks :( I sent you an email :) |
| ||
Guys, can someone tell me how to overcome the following problem? When running the following code, to read more than one layer from my tile map, I'm getting Monkey Runtime Error : Null object access on the line item = item.GetNextSibling("layer") 'load xml Local err:XMLError Local xml:= ParseXML(LoadString("level01.tmx"), err) If xml = Null Error("doh! can't read xml!") If err <> Null Then Print err Local item:XMLNode = xml item = item.GetChild("layer") While item.valid Local name$ = item.GetAttribute("name") Print name Select name Case "Layer1" LevelHeight = Int(item.GetAttribute("height")) LevelWidth = Int(item.GetAttribute("width")) 'Grab level data 'Print LevelWidth+","+LevelHeight Local LevDat:String = item.GetChild("data").value 'Print LevDat Local x=0,y=0 For Local tempDat$ = Eachin LevDat.Split(",") If x < 400 And y < 400 Then LevelMap[x +400* y]=Int(tempDat.Trim()) x=x+1 If x=LevelWidth Then y=y+1 x=0 End If Next Case "Layer2" ' copy+paste of above code for now LevelHeight = Int(item.GetAttribute("height")) LevelWidth = Int(item.GetAttribute("width")) 'Grab level data Print LevelWidth+","+LevelHeight Local LevDat:String = item.GetChild("data").value Print LevDat Local x=0,y=0 For Local tempDat$ = Eachin LevDat.Split(",") If x < 400 And y < 400 Then LevelMap[x +400* y]=Int(tempDat.Trim()) x=x+1 If x=LevelWidth Then y=y+1 x=0 End If Next End Select 'next item item = item.GetNextSibling("layer") Wend Any idea what I'm doing wrong? |
| ||
Hey it looks correct as far as I can see. Just checked the module source and its returning the nullNode properly if there is no nextsibling. What version of the xml lib are you using? |
| ||
16 I assume. thats the first one listed at the top of the file anyway... [edit] just noticed its up to 21, ill give that a try :) |