在Haxe中使用XML值定义多个变量

时间:2014-08-25 20:24:39

标签: xml parsing variables haxe stencyl

我正在尝试在Haxe中编写一个名为Stencyl的程序代码。我试图从Web服务器返回XML响应中的所有日期,并为它们分配变量。我已经获得了基本的XML响应,并且能够使用Fast XML调用,但不知道如何将所有数据定义为要在程序中使用的变量。标签数量可能会因呼叫而异。这是我到目前为止所做的,但不知道如何将整个文档解析为变量。以下是XML数据示例。任何帮助都会很棒!

// 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;

一些示例XML代码

<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>

以下是完整的代码,它现在不会在我更改之前打印vMixData。

{
    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)
{}}

1 个答案:

答案 0 :(得分:1)

您可以使用它来遍历节点:

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);
}

要遍历特定名称的所有节点,请使用“nodes”而不是“node”。像这样使用它将返回指定名称的第一个节点:

var input = fast.node.input;
编辑:好的,让我更好地解释一下。要遍历节点并收集数据,您应该这样做:

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;

对于您发布的XML文件等长XML文件,创建一个将从节点和属性接收值的自定义对象更有意义,这将使您的代码更有条理。我使用像这样的本地变量只是为了更好地说明基本用法。希望这有助于你更好地理解sintax。

为了说明自定义对象的创建,这里是Input类的样子(这是基本的):

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() { }
}

有关Haxe语言的更多信息,我建议您参考手册:

Haxe manual

旧的Haxe网站还有这个快速使用参考:

Using haxe.xml.Fast

此致

  • Tiago Ling Alexandre