0

我正在尝试在名为 Stencyl 的程序中用 Haxe 编写代码。我试图从 Web 服务器返回 XML 响应中获取所有日期,并为它们分配变量。我已经获得了基本的 XML 响应,并且能够使用快速 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)
{}}
4

1 回答 1

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 文件(例如您发布的文件),创建一个自定义对象更有意义,该对象将从节点和属性接收值,这将使您的代码更有条理。我使用这些本地变量只是为了更好地说明基本用法。希望这可以帮助您更好地理解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 网站也有这个快速使用参考:

使用 haxe.xml.Fast

问候,

  • 蒂亚戈·灵·亚历山大
于 2014-08-25T20:45:53.920 回答