Shoutbox

HELP - Selecting XML nodes... - Printable Version

-Shoutbox (https://shoutbox.menthix.net)
+-- Forum: MsgHelp Archive (/forumdisplay.php?fid=58)
+--- Forum: Messenger Plus! for Live Messenger (/forumdisplay.php?fid=4)
+---- Forum: Scripting (/forumdisplay.php?fid=39)
+----- Thread: HELP - Selecting XML nodes... (/showthread.php?tid=92758)

HELP - Selecting XML nodes... by whiz on 11-01-2009 at 03:27 PM

I've gone back to working on Interface Writer - specifically the bit that loads XML files.  It's a long bit of code, so I've put it in a spoiler tag.  :P

Spoiler:
js code:
function OnEvent_Initialize(MessengerStart)
{
    var Interface = LoadInterface(MsgPlus.ScriptFilesPath + "\\" + "Windows.xml");
    var JSONO = new JSON();
    var JSONSource = JSONO.toJSON(Interface);
    WndWriterViewSource = MsgPlus.CreateWnd("Windows.xml", "WndWriterViewSource", 0);
    WndWriterViewSource.RichEdit_SetCharFormat("EdtSource", false, -1, -1, -1, -1, -1, -1, "Lucida Console");
    WndWriterViewSource.SetControlText("EdtSource", "JSON Output of \"Windows.xml\"\n\n-----\n\n" + JSONSource);
}

function LoadInterface(File)
{
    var XMLO = new ActiveXObject("Microsoft.XMLDOM");
    var Interface = new Object();
    Interface.Ok = true;
    if (!XMLO.load(File))
    {
        Interface.Ok = false;
        Interface.Error = XMLO.parseError.reason + "Line number: " + XMLO.parseError.line + " (position " + XMLO.parseError.linepos + ").";
        XMLO = null;
        return Interface;
    }
    if (XMLO.selectSingleNode("//Interfaces/Window") === null)
    {
        Interface.Ok = false;
        Interface.Error = "The interface file must contain a root <Interfaces> tag, as well as at least one window.";
        XMLO = null;
        return Interface;
    }
    Interface.Window = new Object();
    Interface.WindowId = new Array();
    var WindowEnum = new Enumerator(XMLO.selectNodes("//Interfaces/Window"));
    for (; !WindowEnum.atEnd(); WindowEnum.moveNext())
    {
        var WindowNode = WindowEnum.item();
        var WindowId = WindowNode.getAttribute("Id");
        Interface.WindowId.push(WindowId);
        Interface.Window[WindowId] = new Object();
        Interface.Window[WindowId].Control = new Object();
        Interface.Window[WindowId].ControlId = new Array();
        var ControlEnum = new Enumerator(XMLO.selectNodes("//Interfaces/Window[@Id=\"" + WindowId + "\"]/Controls/Control"));
        if (ControlEnum.count() > 0)
        {
            for (; !ControlEnum.atEnd(); ControlEnum.moveNext())
            {
                var ControlNode = ControlEnum.item();
                var ControlId = ControlNode.getAttribute("Id");
                var ControlType = ControlNode.getAttribute("xsi:type");
                if (ControlId in Interface.Window[WindowId].Control)
                {
                    ErrorDialog("Warning: two controls share the name \"" + ControlId + "\" in window \"" + WindowId + "\".\nThe second occurrence of this control name will be ignored.", "Load Interface File");
                }
                else
                {
                    Interface.Window[WindowId].ControlId.push(ControlId);
                    Interface.Window[WindowId].Control[ControlId] = new Object();
                    var ControlPosEnum = new Enumerator(XMLO.selectNodes("//Interfaces/Window[@Id=\"" + WindowId + "\"]/Controls/Control[@Id=\"" + ControlId + "\"]/Position"));
                    if (ControlPosEnum.count() == 0)
                    {
                        ErrorDialog("Warning: no position tag found for control \"" + ControlId + "\" in window \"" + WindowId + "\".", "Load Interface File");
                    }
                    else
                    {
                        Interface.Window[WindowId].Control[ControlId].Position = new Object();
                        for (; !ControlPosEnum.atEnd(); ControlPosEnum.moveNext())
                        {
                            var ControlPosNode = ControlPosEnum.item();
                            Interface.Window[WindowId].Control[ControlId].Position.Left = ControlPosNode.getAttribute("Left").toString();
                            Interface.Window[WindowId].Control[ControlId].Position.Top = ControlPosNode.getAttribute("Top").toString();
                            Interface.Window[WindowId].Control[ControlId].Position.Width = ControlPosNode.getAttribute("Width").toString();
                            try
                            {
                                Interface.Window[WindowId].Control[ControlId].Position.Height = ControlPosNode.getAttribute("Height").toString();
                            }
                            catch (error)
                            {
                            }
                        }
                    }
>>>                    var ControlCaption = XMLO.selectSingleNode("//Interfaces/Window[@Id=\"" + WindowId + "\"]/Controls/Control[@Id=\"" + ControlId + "\"]/Caption"); <<<
>>>                    Debug.Trace(ControlCaption); <<<
                }
            }
        }
        Interface.Window[WindowId].Element = new Object();
        Interface.Window[WindowId].ElementId = new Array();
        var ElementEnum = new Enumerator(XMLO.selectNodes("//Interfaces/Window[@Id=\"" + WindowId + "\"]/Elements/Element"));
        if (ElementEnum.count() > 0)
        {
            for(; !ElementEnum.atEnd(); ElementEnum.moveNext())
            {
                var ElementNode = ElementEnum.item();
                var ElementId = ElementNode.getAttribute("Id");
                var ElementType = ElementNode.getAttribute("xsi:type");
                if (ElementId in Interface.Window[WindowId].Element)
                {
                    ErrorDialog("Warning: two elements share the name \"" + ElementId + "\" in window \"" + WindowId + "\".\nThe second occurrence of this control name will be ignored.", "Load Interface File");
                }
                else
                {
                    Interface.Window[WindowId].ElementId.push(ElementId);
                    Interface.Window[WindowId].Element[ElementId] = new Object();
                    var ElementPosEnum = new Enumerator(XMLO.selectNodes("//Interfaces/Window[@Id=\"" + WindowId + "\"]/Controls/Element[@Id=\"" + ElementId + "\"]/Position"));
                    if (ElementPosEnum.count() == 0)
                    {
                        ErrorDialog("Warning: no position tag found for element \"" + ControlId + "\" in window \"" + WindowId + "\".", "Load Interface File");
                    }
                    else
                    {
                        Interface.Window[WindowId].Element[ElementId].Position = new Object();
                        for (; !ElementPosEnum.atEnd(); ElementPosEnum.moveNext())
                        {
                            var ElementPosNode = ElementPosEnum.item();
                            Interface.Window[WindowId].Element[ElementId].Position.Left = ElementPosNode.getAttribute("Left").toString();
                            Interface.Window[WindowId].Element[ElementId].Position.Top = ElementPosNode.getAttribute("Top").toString();
                            Interface.Window[WindowId].Element[ElementId].Position.Width = ElementPosNode.getAttribute("Width").toString();
                            try
                            {
                                Interface.Window[WindowId].Element[ElementId].Position.Height = ElementPosNode.getAttribute("Height").toString();
                            }
                            catch (error)
                            {
                            }
                        }
                    }
                }
            }
        }
    }
    XMLO = null;
    return Interface;
}

Enumerator.prototype.count = function()
{
    var i = 0;
    while (!this.atEnd())
    {
        this.moveNext();
        i++
    }
    this.moveFirst();
    return i;
}

The highlighted line throws a type mismatch error.  Using nodeObj.getAttribute() works for something like <Tag Value="String"/>, but I want to get something like <Tag>String</Tag>.  How would I go about this, since I only just understand the basics of the XML DOM object...
RE: HELP - Selecting XML nodes... by Matti on 11-01-2009 at 09:06 PM

The type mismatch is because you're trying to send an Element object as parameter to Debug.Trace, and the scripting engine doesn't know how to convert that object to a string. (It would work if the object had a toString() method defined, but it doesn't.)

To read the content of an Element, you use the text property. In your case, that would be as simple as:

js code:
Debug.Trace(ControlCaption.text);

And here's a nice reference of the XML DOM at DevGuru or at MSDN. So next time you're puzzled on something, go have a look there. They're both very complete and comprehensive, both for the newbie scripter as the experienced developer. :)
RE: HELP - Selecting XML nodes... by whiz on 11-02-2009 at 01:33 PM

Ah.  ;)  Thanks!