如何在不知道级别的情况下获得具有相同名称的所有XML节点

本文关键字:节点 XML 不知道 情况下 | 更新日期: 2023-09-27 18:22:49

我有一个XML示例:

<Fruits>
    <Red_fruits>
        <Red_fruits></Red_fruits>
    </Red_fruits>
    <Yellow_fruits>
        <banana></banana>
    </Yellow_fruits>
    <Red_fruits>
        <Red_fruits></Red_fruits>
    </Red_fruits>
</Fruits>

我有4个Red_fruits标签,其中2个共享相同的ParentNode(fruits),我想得到那些具有相同ParentNode的标签。

但我只想要那些同名的(Red_fruits),这意味着Yellow_fruits标签不包括在内。

这就是我现在使用C#语言的方式:

XmlDocument doc = new XmlDocument();
string selectedTag = cmbX.text;
if (File.Exists(txtFile.text))
{
    try
    {
        //Load
        doc.Load(cmbFile.text);
        //Select Nodes
        XmlNodeList selectedNodeList = doc.SelectNodes(".//" + selectedTag);
    }
    Catch
    {
        MessageBox.show("Some error message here");
    } 
 }

这是还给我所有的红色水果,而不仅仅是那些属于水果的。

我无法使XmlNodeList=doc。SelectNodes("/Fuits/Red_fuits"),因为我想使用此代码读取随机的XML文件,所以我不知道特定节点的确切名称,我只需要使用C#语言将所有具有相同名称和级别的节点放入XmlNodeList中。

有没有一种方法可以在不使用LINQ的情况下实现这一点?如何做到这一点?

如何在不知道级别的情况下获得具有相同名称的所有XML节点

了解单斜杠/和双斜杠//的用法可以在这里有所帮助。

让我们看看///是如何与根节点相关地工作的。当/用于路径的开头时:

/a

它将定义相对于根到节点CCD_ 6的绝对路径。因此,在这种情况下,它将只在XML树的根处找到a节点。

//用于路径的开头时:

//a

它将定义到XML文档中任意位置的节点CCD_ 9的路径。因此,在这种情况下,它将找到位于XML树中任何深度的a节点。

这些XPath表达式也可以用于XPath值的中间,以定义ancestor-descendant关系。在路径中间使用/时:

/a/b

它将定义到作为节点CCD_ 13的直接后代(即子代)的节点b的路径。

在路径中间使用//时:

/a//b

它将定义到节点CCD_ 15的路径,该路径是节点aANY子代。

回到你的问题:

//使用GetElementsByTagName()返回所有名为Red_Fuits 的元素

XmlDocument doc = new XmlDocument();
XmlNodeList nodes= doc.GetElementsByTagName("Red_Fruits"); 

//使用SelectNodes()方法

XmlNodelist nodes = doc.SelectNodes("//Fruits/Red_Fruits"); 

//这将选择作为<Fruits>元素的子元素的所有元素。

如果<Fruits>是根元素,请使用Xpath:/Fruits/Red_Fruits。[单斜线/]

如果您只是想找到单个节点的"下一个"或"上一个"迭代,您可以执行以下操作,然后将其与名称进行比较

XmlNode current = doc.SelectSingleNode("Fruits").SelectSingleNode("Red_fruits");
XmlNode previous = current.NextSibling;
XmlNode next = current.NextSibling;

并且您可以进行迭代,直到找到合适的同级

while(next.Name != current.Name)
{
    next = next.NextSibling;
}

或者您甚至可以通过调用"Parent"属性来获取您的列表

XmlNodeList list = current.ParentNode.SelectNodes(current.Name);

在最坏的情况下,您可以循环浏览selectedNodeList中的XMLNode项并检查ParentNode属性。如果需要,可以递归ParentNode检查,并计算到达根节点所需的次数。这将提供节点的深度。或者,您可以比较每个级别的ParentNode,看看它是否是您感兴趣的父节点,如果该父节点不是根节点。

    public void Test(){

        XmlDocument doc = new XmlDocument();
        string selectedTag = cmbX.text;
        if (File.Exists(txtFile.text))
        {
            try
            {
                //Load
                doc.Load(cmbFile.text);
                //Select Nodes
                XmlNodeList selectedNodeList = doc.SelectNodes(".//" + selectedTag);
                List<XmlNode> result = new List<XmlNode>();
                foreach(XmlNode node in selectedNodeList){
                    if(depth(node) == 2){
                        result.Add(node);
                    }
                }
                // result now has all the selected tags of depth 2
            }
            Catch
            {
                MessageBox.show("Some error message here");
            } 
        }
    }
    private int depth(XmlNode node) {
        int depth = 0;
        XmlNode parent = node.ParentNode;
        while(parent != null){
            parent = node.ParentNode;
            depth++;
        }
        return depth;
    }