如何判断XML中指定Database节点是否存在子节点?无则返回false,有则返回true
Hey there, I see where you went wrong here! Your XML structure uses <node> elements for every entry, with the text attribute defining what each node represents. But your original code was trying to select elements by names like "California" or "Database"—which don't exist as element names in your XML. Let's fix that, plus give you working solutions for all the approaches you tried, including XmlTextReader.
1. Fixed XPath Approach
The key fix here is adjusting your XPath query to filter <node> elements by their text attribute, instead of treating those text values as element names. We'll also explicitly check for child <node> elements to avoid counting text nodes or whitespace.
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(); // Target the Database node under the parent node using @text attributes string xpathQuery = $"//Profile/node[@text='{selNodeParentName}']/node[@text='{selNodeName}']"; XPathNavigator targetDbNode = navigator.SelectSingleNode(xpathQuery); if (targetDbNode != null) { // Check if the node has child <node> elements (ignore whitespace/text nodes) bool hasChildNodes = targetDbNode.SelectChildren("node", string.Empty).Count > 0; TsmNewDb.Enabled = !hasChildNodes; // Disable if children exist, enable otherwise } else { TsmNewDb.Enabled = true; // Fallback if node isn't found } } catch { TsmNewDb.Enabled = true; }
2. Corrected LINQ to XML Method
Same core issue here—you were looking for elements named after your node text values, not filtering <node> elements by their text attribute. Here's the fixed version:
selNodeParentName = TvwPanel.SelectedNode.Parent.Text; selNodeName = TvwPanel.SelectedNode.Text; Save_Treeview_To_Xml xcf = new Save_Treeview_To_Xml(); XElement xmlComplete = XElement.Load(xcf.xmlProfileComplete); // Navigate to the parent node first, then find its Database child var parentNode = xmlComplete.Descendants("node") .FirstOrDefault(n => n.Attribute("text")?.Value == selNodeParentName); var targetDbNode = parentNode?.Elements("node") .FirstOrDefault(n => n.Attribute("text")?.Value == selNodeName); if (targetDbNode != null) { int childNodeCount = targetDbNode.Elements("node").Count(); TsmNewDb.Enabled = childNodeCount == 0; // Enable only if no children } else { TsmNewDb.Enabled = true; }
3. Efficient XmlTextReader Implementation
If you're dealing with large XML files, XmlTextReader is a great choice since it streams the data instead of loading the whole document into memory. Here's how to use it for your scenario:
selNodeParentName = TvwPanel.SelectedNode.Parent.Text; selNodeName = TvwPanel.SelectedNode.Text; Save_Treeview_To_Xml xcf = new Save_Treeview_To_Xml(); bool dbHasChildren = false; bool isInParentNode = false; bool isInDbNode = false; using (XmlTextReader reader = new XmlTextReader(xcf.xmlProfileComplete)) { while (reader.Read()) { if (reader.NodeType == XmlNodeType.Element && reader.Name == "node") { string nodeText = reader.GetAttribute("text"); switch (nodeText) { case var text when text == selNodeParentName: isInParentNode = true; break; case var text when isInParentNode && text == selNodeName: isInDbNode = true; break; case var text when isInDbNode: // We found a child node under Database—no need to read further dbHasChildren = true; goto ExitLoop; // Cleanly exit the loop } } else if (reader.NodeType == XmlNodeType.EndElement && reader.Name == "node") { // Exit parent/Database node context when we hit the closing tag if (isInDbNode) isInDbNode = false; else if (isInParentNode) isInParentNode = false; } } ExitLoop: ; } TsmNewDb.Enabled = !dbHasChildren;
All these solutions fix the core mistake of confusing element names with the text attribute values. Pick the approach that best fits your project's needs—LINQ is great for readability, XPath is flexible, and XmlTextReader is ideal for large files.
内容的提问来源于stack exchange,提问作者RickyBelmont

