How to check if certain Node Attribute has Children? If there is none, returns "false". Otherwise, returns "true"

327 views Asked by At

Here's the xml file I am trying to check if it has child nodes triggered by TreeView SelectedNode on Database node:

    <?xml version="1.0" encoding="us-ascii"?>
    <Profile>
        <node text="California" tag="a" imageindex="0">
            <node text="Database" tag="b" imageindex="1">
                <node text="Type" tag="MySQL Server" imageindex="-1" />
                <node text="Name" tag="alona" imageindex="-1" />
                <node text="Connection" tag="Server=localhost; UID=root; PWD= ????????" imageindex="-1" />
            </node>
            <node text="Company File" tag="c" imageindex="2" />
            <node text="Tasks" tag="d" imageindex="3" />
            <node text="Logs" tag="e" imageindex="4" />
        </node>
        <node text="New Orleans" tag="a" imageindex="0">
            <node text="Database" tag="b" imageindex="1" />
            <node text="Company File" tag="c" imageindex="2" />
            <node text="Tasks" tag="d" imageindex="3" />
            <node text="Logs" tag="e" imageindex="4" />
        </node>
    </Profile>

The above xml file is generated by the TreeView and the data like California and New Orleans are user defined including the children of the text="Database".

Now, I just want to check if Database node has children?

Here's what I have so far and got lost with SelectSingleNode, both TsmNewDb property returns true:

    selNodeParentName = TvwPanel.SelectedNode.Parent.Text;
    selNodeName = TvwPanel.SelectedNode.Text;

    Save_Treeview_To_Xml xcf = new Save_Treeview_To_Xml();

    try
    {
        XPathDocument document = new XPathDocument(xcf.xmlProfileComplete);
        XPathNavigator navigator = document.CreateNavigator();
        XPathNavigator node = navigator.SelectSingleNode("//Profile/" + selNodeParentName + "/" + selNodeName);
                
        if (node != null)
        {
            TsmNewDb.Enabled = false;
        } 
    }
    catch
    {
        TsmNewDb.Enabled = true;
    }

If you have better ways, please feel free to suggest your own code. I read XmlTextReader is a lot faster but haven't figured out how yet.

UPDATE 1: I am attempting to use now Linq to Xml but having issue with int var below childrenCount that returns 0 either California or New Orleans elements.

    selNodeParentName = TvwPanel.SelectedNode.Parent.Text; //tested result "California"
    selNodeName = TvwPanel.SelectedNode.Text;              //tested result "Database"

    Save_Treeview_To_Xml xcf = new Save_Treeview_To_Xml(); 

    XElement xmlComplete = XElement.Load(xcf.xmlProfileComplete);  //loaded successfully
    int childrenCount = xmlComplete.Descendants(selNodeParentName).Elements(selNodeName).Count();

    MessageBox.Show(childrenCount .ToString()); // result always 0

    if (childrenCount > 0)
    {
        TsmNewDb.Enabled = false; // TreeView ContextMenu button
    }
    else
    {
        TsmNewDb.Enabled = true; // TreeView ContextMenu button
    }
1

There are 1 answers

5
Conal Tuohy On

It's hard to tell what's going on because you don't indicate what the value of selNodeParentName and selNodeName are. I assume they'd be something like node[@text='California'] and node[@text='database'], respectively? Though if the result of TsmNewDb.Enabled ends up as true does that imply an exception was thrown?

But to answer your question; once you've found the element whose name attribute is database, you can use the SelectChildren method of XPathNavigator to query for its children: https://learn.microsoft.com/en-us/dotnet/api/system.xml.xpath.xpathnavigator.selectchildren?view=net-6.0

If you pass String.Empty as the value of both parameters, you will get an iteration of all child nodes (with any name and namespace). If there are no children, the iterator's Count property will be zero.