简体   繁体   中英

Javascript get a node at a specific path within XML

I'm reading some XML into a XmlDocument using the following code:

if (window.DOMParser)
{
    oParser = new DOMParser();
    oXml = oParser.parseFromString(this._code, "text/xml");
}
else // Internet Explorer
{
    oXml = new ActiveXObject("Microsoft.XMLDOM");
    oXml.async = false;
    oXml.loadXML(this._code);
}

The test XML looks like this:

<Macro>
  <StepCount>1</StepCount>
  <Step0>
    <StepType>CLOSEFORM</StepType>
    <Description>Close Form</Description>
    <OnSuccess>NEXTSTEP</OnSuccess>
    <OnFailure>SHOWERRORSANDSTOP</OnFailure>
    <CheckWithUser>False</CheckWithUser>
    <UserOptions>
        <Description>
            Are you sure you want to close the form?
        </Description>
    </UserOptions>
  </Step0>
</Macro>

The XML has been designed so that each node within it has a unique path (hence the tag Step0 rather than just Step ). I'm aware that XML doesn't conform to this restriction normally. I'm trying to use oXml.getElementsByTagName , which should return an array of nodes that match the tag name.

I'd like to be able to obtain the value of at a specific path, for example: /Macro/Step0/Description" .

However, if I use getElementsByTagName , I can only specify "Description" as the tag name, which will return me two nodes, one I want and one from deeper in the XML. If there are multiple Steps (Step1, Step2 etc), I will also get multiple Descriptions back that I'm uninterested in.

Is there another method where I can specify the path to the node? I don't mind getting an array back, as in this case, the array will only ever contain one element, given the restriction indicated. I'm aware of document.evaluate , but that only applies to the HTML document.

Alternatively, if I have an element that I've obtained using getElementsByTagName how do I get it's full path?

Well, I've derived an solution, but there may be a better way (I hope so). The approach I've used is to get all nodes that match the last tag of the path using getElementsByTagName . The run through those deriving the full path, and returning the first item that matches the full path. Not elegant, and I certainly wouldn't use it on a large dataset, but it works for the volume of data I'm looking at.

The code is:

function XmlDeriveFullPath(element) // returns the full path to the element within the XML, assuming that each node has a unique path
{
    var cPath = "/" + element.tagName;

    while ((element.parentNode != null) && (element.parentNode != undefined))
    {
        element = element.parentNode;
        if (element.tagName != null)
            cPath = "/" + element.tagName + cPath;
    }
    return cPath;
}

function XmlGetValueStr(oXml, cPath, cDefault = "") // Returns the value of the first node matching path. On error or no node, returns cDefault
{
    var aPath;
    var cLastTag;
    var i;
    var cFullPath;

    try
    {
        // get the last tag in the path
        aPath = cPath.split("/");
        cLastTag = aPath[aPath.length - 1];

        var elements = oXml.getElementsByTagName(cLastTag); // gives us a list of items with the same tag
        for (i=0; i<elements.length; i++)
        {
            cFullPath = XmlDeriveFullPath(elements[i]);
            if (cFullPath == cPath)
            {
                return elements[i].firstChild.nodeValue;
            }
        }

        return cDefault;
    }
    catch (e)
    {
        console.log("#XmlGetNodeStr: " + e);
        throw e;
    }
}

function XmlGetValueInt(oXml, cPath, iDefault = 0) // Returns the value of the first node matching path
{   
    var cValue;
    var iValue;

    try
    {
        cValue = XmlGetNodeStr(oXml, cPath, "");
        iValue = parseInt(cValue);
        return iValue;
    }
    catch (e)
    {
        console.log("#XmlGetNodeInt: " + e);
        return iDefault;
    }
}

iStepCount = XmlGetValueInt(oXml, "/Macro/StepCount", 0);

If someone does have a better solution, please post.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM