0

如,如果我有一个 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 上执行它。

请协助。

非常感谢,

4

4 回答 4

5

您的第二个 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);
于 2009-06-14T16:00:07.243 回答
2

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

于 2009-06-14T16:00:05.823 回答
0

你可以做一个 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();
    }
}
于 2009-06-15T09:57:42.623 回答
0

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

于 2021-07-30T08:46:08.127 回答