2

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
    }
RickyBelmont
  • 619
  • 4
  • 11

1 Answers1

1

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.

Conal Tuohy
  • 2,561
  • 1
  • 8
  • 15
  • I've tried your suggestion but it appears to be a long shot procedure. I am looking at a straight forward `Yes or No` answer from the code. The reason is I will be using this as a method across my project. I am trying right now `Linq to Xml` approach. I will update my attempt here. – RickyBelmont Jul 09 '22 at 23:57
  • 1
    It's clear what your bug is now; it's the same as the original bug using XPath; in both cases you are querying for an element whose name is `California`, but that's not the element's name; it's the value of the element's `name` attribute; the element's _name_ is `node`. – Conal Tuohy Jul 10 '22 at 01:31
  • Oh my goodness! I didn't see that! Yes, you are right I just verified it! I've been trying different approach but all failed. I've been messing around this for 5 hours already. Thank you thank you. Now, the challenge is how to get to the attribute. – RickyBelmont Jul 10 '22 at 01:37
  • 1
    Using the XPath code, you could try `XPathNavigator node = navigator.SelectSingleNode("//Profile/node[@name='" + selNodeParentName + "']/node[@name='" + selNodeName + "']");` – Conal Tuohy Jul 10 '22 at 07:00
  • I tried your suggestion but there still some fixing needed. I was able to find a workaround but it is a long route. I am not sure if its worth posting here. I used `Linq to Xml`. – RickyBelmont Jul 10 '22 at 08:09