Reputation: 141
I am trying to write a code in in Haxe in a program called Stencyl. I am trying to take all of the date in a return XML response from a web server and assign variables to them. I have gotten the basic XML response and was able to use the Fast XML call but do not know how to define all the data into variables to be used in the program. The number of tags may change from call to call. Here is what I have so far but do not know how to parse the whole document into variables. Below is also sample XML data. Any help would be awesome!
// parse some xml data
var xml = Xml.parse(_vMixData).firstElement();
// wrap the xml for fast access
var fast = new haxe.xml.Fast(xml.firstElement());
// access the "inputs" child, which is wrapped with haxe.xml.Fast too
var inputs = fast.node.inputs;
Some Sample XML Code
<vmix>
<version>14.0.0.52</version>
<inputs>
<input key="7715f2db-bdfd-4a7b-ab50-206dd26411cf" number="1" type="Video" title="Dord..mp4" state="Paused" position="0" duration="776214" loop="False" muted="False" volume="100" solo="False" audiobusses="M">Dord..mp4</input><input key="e5362e83-84e3-4b12-84c0-c18dad12570d" number="2" type="Blank" title="Blank" state="Paused" position="0" duration="0" loop="False">Blank</input>
</inputs>
<overlays>
<overlay number="1">Input.mp4</overlay>
<overlay number="2" />
<overlay number="3" />
<overlay number="4" />
<overlay number="5" />
<overlay number="6" />
</overlays>
<preview>2</preview>
<active>1</active>
<fadeToBlack>False</fadeToBlack>
<transitions>
<transition number="1" effect="Zoom" duration="500" />
<transition number="2" effect="Wipe" duration="500" />
<transition number="3" effect="Fly" duration="500" />
<transition number="4" effect="Zoom" duration="1000" />
</transitions>
<recording>False</recording>
<external>False</external>
<streaming>False</streaming>
<playList>False</playList>
<multiCorder>False</multiCorder>
<audio>
<master volume="100" muted="False" headphonesVolume="100" />
</audio>
</vmix>
Here is the code in its entirety and it now doesnt print vMixData where it used to before I changed it.
{
public var _Prog1:Actor;
public var _vMixData:String;
public var _inputvar:String;
public function new(dummy:Int, engine:Engine)
{
super(engine);
nameMap.set("Prog 1", "_Prog1");
nameMap.set("vMixData", "_vMixData");
_vMixData = "";
nameMap.set("inputvar", "_inputvar");
_inputvar = "";
}
override public function init()
{
/* ======================= Every N seconds ======================== */
runPeriodically(1000 * 1, function(timeTask:TimedTask):Void
{
if (wrapper.enabled)
{
visitURL("http://127.0.0.1:8088/api?/Function=", function(event:Event):Void
{
_vMixData = cast(event.target, URLLoader).data;
propertyChanged("_vMixData", _vMixData);
});
var xml = Xml.parse(_vMixData);
// wrap the xml for fast access
var fast = new haxe.xml.Fast(xml.firstElement());
// access the "inputs" child, which is wrapped with haxe.xml.Fast too
var input = fast.node.input;
for (input in fast.node.input)
{
//Checking for and accessing attributes.
if (input.has.key)
trace("Input key : " + input.att.key);
//Accessing contents of a node
trace("Contents of input node : " + input.innerHTML);
}
trace("" + _vMixData);
}
}, null);
}
override public function forwardMessage(msg:String)
{}}
Upvotes: 0
Views: 783
Reputation: 131
You can use this to loop through nodes:
for (input in fast.nodes.input) {
//Checking for and accessing attributes.
if (input.has.key)
trace("Input key : " + input.att.key);
//Accessing contents of a node
trace("Contents of input node : " + input.innerHTML);
}
To loop through all nodes of a specific name you use 'nodes' instead of 'node'. Using it like this would return the first node of the specified name:
var input = fast.node.input;
EDIT: Alright, let me explain this a little better. To loop through your nodes, and gather your data, you should do this:
var xml = Xml.parse(_vMixData);
// wrap the xml for fast access
var data = new haxe.xml.Fast(xml.firstElement());
//Getting the data from inputs (here we are getting the xml node 'inputs', which contain two 'input' nodes, as per your sample xml file.
var inputs = data.node.inputs;
//Here we are creating an array which will store your input objects - you can access each one through the array access operator: ipts[0], ipts[1], etc. Each number will access one of the 'ipt' objects you will create below (you will receive an error if you try to access an index greater than the array length - 1)
var ipts = new Array<Input>();
//Looping through child nodes of inputs (notice i wrote 'nodes', not 'node')
for (input in inputs.nodes.input) {
//In each iteration the object 'input' will contain data from one of the child nodes
//Create a new Input object - this would be a custom class created by you.
var ipt = new Input();
//For example, this will let you access the state attribute
if (input.has.state) { //here we check if the attribute actually exists before trying to get its data
//Assign values from data to your recently created custom object
ipt.state = input.att.state;
}
//You can access any of the attributes in this way
if (input.has.volume)
ipt.volume = Std.parseInt(input.att.volume); //All XML data will come as strings, so we must parse numbers before using them
//Accessing data from the node
ipt.value = input.innerHTML;
//Finally, store your 'ipt' object inside an array to be able to access the data later. The command push will insert the new input at the last index of the array.
ipts.push(ipt);
}
//In the same way we did for the 'inputs' node we can parse the 'transitions'
var transitions = null;
if (data.hasNode.transitions) //Checking if the node actually exists
transitions = data.node.transitions;
//Note that the object name could be any one - it does not have to be same name as the actual XML node
var trans = new Array<Transition>(); //Remember, 'Transition' here means a custom object which you can create to store data from the XML. It does not necessarily has to have this specific name.
for (tData in transitions.nodes.transition) {
var trn = new Transition();
trn.effect = tData.att.effect;
trn.duration = Std.parseInt(tData.att.duration);
}
//Finally, you can access individual nodes by simple referencing them directly (without loops or accessing a set of nodes
var version:String = data.node.version.innerHTML;
var fadeToBlack:Bool = data.node.fadeToBlack.innerHTML == "True" ? true : false;
For long XML files such as the one you posted, it makes more sense to create a custom object which will receive the values from nodes and attributes, this will make your code more organized. I used local vars like these just to better illustrate the basic usage. Hope this helps you understand the sintax a little better.
To illustrate the custom object creation, here is what the Input class could look like (this is as basic as it gets):
class Input
{
public var state:String;
public var volume:Int;
public var value:String;
//And so on, listing all the fields from the XML attributes and values.
public function new() { }
}
For more information regarding Haxe language in general, i'd recommend consulting the manual:
There is also this Fast usage reference from the old Haxe site:
Regards,
Upvotes: 1