【问题标题】:C # SelectSingleNode - Can it be used recursively?C# SelectSingleNode - 可以递归使用吗?
【发布时间】:2009-06-14 15:54:50
【问题描述】:

如果我有一个 XML 文档

<root a="value">
    <item name="first">
        x
        <foo name = "firstgrandchild">There is nothing here</foo>
        y
        <foo name = "secondgrandchild">There is something here</foo> 
    </item>
    <item name="second">
        xy
        <foo/>
        ab
    </item>
</root>

我想先找到节点“item”的第一次出现然后更新属性,然后我想更新节点“foo”的第一次出现然后更新属性等等,

我的代码如下

myDoc.Load("Items2.xml");
myNode = myDoc.DocumentElement;
mySearchNode = myNode.SelectSingleNode("/root/item");
mySearchNode.Attributes["name"].Value = "Joel";
Console.WriteLine(mySearchNode.OuterXml);
mySearchChildNode = mySearchNode.SelectSingleNode("/item/foo");
Console.WriteLine(mySearchChildNode.OuterXml);

虽然第一次搜索和更新属性工作正常,但第二次失败,因为 mySearchNode.SelectSingleNode 返回 null。

问题 - 这段代码是否存在根本问题? 为什么 SelectSingleNode 在第二个实例中没有按预期工作,就它而言,我在 Element 类型的 XmlNode 上执行它。

请提供帮助。

非常感谢,

【问题讨论】:

    标签: c# xml selectsinglenode


    【解决方案1】:

    您的第二个 XPath 查询应该没有前导斜杠。 / 表示“文档的根”。如果您省略斜杠,则查询将与您的 mySearchNode 变量相关。您也不应该再次包含“item”,您的查询与您选择的“item”节点相关。在代码中:

    myDoc.Load("Items2.xml");
    myNode = myDoc.DocumentElement;
    mySearchNode = myNode.SelectSingleNode("/root/item");
    mySearchNode.Attributes["name"].Value = "Joel";
    Console.WriteLine(mySearchNode.OuterXml);
    mySearchChildNode = mySearchNode.SelectSingleNode("foo");
    Console.WriteLine(mySearchChildNode.OuterXml);
    

    【讨论】:

      【解决方案2】:

      mySearchNode 是 item 节点,因此如果 fooitem 的子节点,则您的第二个 xpath 应该只是 "foo"

      【讨论】:

        【解决方案3】:

        你可以做一个 SelectNodes 然后循环遍历所有的项目节点。对于每个项目,您应该进一步在 foo 节点上执行 SelectNodes。您应该检查节点数以及 item 和 foo 节点的属性名称是否存在。 您可以使用此代码:

        /// <summary>
        /// Changes the xml in sourceFileName and writes the changed xml to destFileName
        /// </summary>
        public static void ProcessNames(string sourceFileName, string destFileName)
        {
            XmlDocument xmlDoc = new XmlDocument();
            XmlTextWriter xtw = null;
            xmlDoc.Load(sourceFileName);
        
            try
            {
                // Parse through all the item nodes and process them
                XmlNodeList itemList = xmlDoc.SelectNodes("//root/item");
        
                if (itemList.Count > 0)
                {
                    foreach (XmlNode item in itemList)
                    {
                        // Change the name attribute, if it exists
                        if (item.Attributes["name"] != null)
                        {
                            string newItemName = item.Attributes["name"].Value + "Joel";
                            item.Attributes["name"].Value = newItemName;
                        }
        
                        // Parse through all the foo nodes and process them
                        XmlNodeList fooList = item.SelectNodes("foo");
        
                        if (fooList.Count > 0)
                        {
                            foreach (XmlNode foo in fooList)
                            { 
                                // Change the name attribute, if it exists
                                if (foo.Attributes["name"] != null)
                                {
                                    string newFooName = foo.Attributes["name"].Value + "Joel";
                                    foo.Attributes["name"].Value = newFooName;
                                }
                            }
                        }
        
                    }
        
                    xtw = new XmlTextWriter(destFileName, Encoding.UTF8);
                    xmlDoc.WriteContentTo(xtw);
                }
        
            }
            finally
            {
                xtw.Close();
            }
        }
        

        【讨论】:

          【解决方案4】:

          据我了解,主要问题是,在节点上调用的 SelectNode(s)(此处为:mySearchNode.SelectSingleNode)无法按预期工作!!!
          它不会从给定节点开始搜索,而是始终从根文档开始搜索。 (另请参阅源代码,其中对于节点,相关的 XmlDocument 节点用于启动 XPathNavigator)
          我完全没想到会有这种行为! 更好地使用应该按预期工作的 XDocument。

          【讨论】:

            猜你喜欢
            • 2019-04-18
            • 1970-01-01
            • 2016-05-31
            • 1970-01-01
            • 2011-12-28
            • 2022-06-25
            • 1970-01-01
            • 2016-11-10
            • 2011-09-13
            相关资源
            最近更新 更多