如何使用C#替换特定的xml节点元素

时间:2016-07-12 20:39:53

标签: c# xml

给定本地xml文件:

<products>
  <product id="p1">
    <name>Delta</name>
    <price>800</price>
    <stock>4</stock>
    <country>Denmark</country>
  </product>
  <product id="p2">
    <name>Golf</name>
    <price>1000</price>
    <stock>5</stock>
    <country>Germany</country>
  </product>
  <product id="p3">
    <name>Alfa</name>
    <price>1200</price>
    <stock>19</stock>
    <country>Germany</country>
  </product>
  <product id="p4">
    <name>Foxtrot</name>
    <price>1500</price>
    <stock>5</stock>
    <country>Australia</country>
  </product>
  <product id="p5">
    <name>Tango</name>
    <price>1225</price>
    <stock>3</stock>
    <country>Japan</country>
  </product>
</products>

我试图将产品节点'p1'中的price元素替换为:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System;
using System.Xml.XPath;
using System.Xml.Linq;

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(@"products.xml");

Console.WriteLine("\n\nDisplay the initial XML...");
xmlDoc.Save(Console.Out);

//Create an XmlNamespaceManager for resolving namespaces.
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("products", "product");

// replace the node with a new one
//Select the profile node with the matching attribute value.
XmlNode product;
XmlElement root = xmlDoc.DocumentElement;
product = root.SelectSingleNode("descendant::product[id='p1']", nsmgr);

//Create a new price element.
XmlElement oldElem = xmlDoc.CreateElement("price");
oldElem.InnerText = "800";

//Create a new price element.
XmlElement newElem = xmlDoc.CreateElement("price");
newElem.InnerText = "125";

//Replace the price element.
root.ReplaceChild(newElem, root.FirstChild);
Console.WriteLine("\n\nDisplay the modified XML...");
xmlDoc.Save(Console.Out);

// save the document with the revised node
xmlDoc.Save(@"products2.xml");

问题是新节点(price)元素被简单地添加到产品p1节点,当保存到磁盘时,该节点将丢弃所有p1。我做错了什么?

3 个答案:

答案 0 :(得分:1)

主要问题在

product = root.SelectSingleNode("descendant::product[id='p1']", nsmgr);

因为你没有在下面使用变量。

下一期问题出现在[id='p1']中,因为您正在像元素一样访问ID,但它应该是一个属性。请改用[@id='p1']

其他事项:

  • 可能会直接更新<price>节点的内部文本,而不是替换整个元素。
  • 不需要命名空间管理器,因为您的示例中没有命名空间。
  • 无需创建节点oldNode。该节点已存在。
  • newElem未使用。

建议你的风格修复:

using System;
using System.Xml;

namespace XmlUpdateNode
{
    class Program
    {
        static void Main()
        {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(@"products.xml");

            Console.WriteLine("\n\nDisplay the initial XML...");
            xmlDoc.Save(Console.Out);

            // replace the node with a new one
            //Select the profile node with the matching attribute value.
            var product = xmlDoc.SelectSingleNode("descendant::product[@id='p1']");

            //Create a new price element.
            XmlElement elem = xmlDoc.CreateElement("price");
            elem.InnerText = "125";

            //Replace the price element.
            product.ReplaceChild(elem, product.FirstChild.NextSibling);
            Console.WriteLine("\n\nDisplay the modified XML...");
            xmlDoc.Save(Console.Out);

            // save the document with the revised node
            xmlDoc.Save(@"products2.xml");
        }
    }
}

直接替换price元素中的文本更短:

using System;
using System.Xml;

namespace XmlUpdateNode
{
    class Program
    {
        static void Main()
        {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(@"products.xml");

            Console.WriteLine("\n\nDisplay the initial XML...");
            xmlDoc.Save(Console.Out);

            // replace the price directly
            var product = xmlDoc.SelectSingleNode("descendant::product[@id='p1']/price");
            product.InnerText = "125";

            Console.WriteLine("\n\nDisplay the modified XML...");
            xmlDoc.Save(Console.Out);

            // save the document with the revised node
            xmlDoc.Save(@"products2.xml");
        }
    }
}

答案 1 :(得分:0)

创建节点并将其附加到代码中的产品节点,而不是创建元素。

<job-xml>

你可以重复上面的代码。您希望在产品节点下使用的节点。

答案 2 :(得分:0)

如果我理解正确,您希望更新pricep1的值。如果是这样,LINQ会很简单。

XDocument xmlDoc = XDocument.Load(@"products.xml");
var product = xmlDoc.Descendants("product")
                  .Where(item => item.Attribute("id").Value == "p1").FirstOrDefault();
product.Element("price").Value = "125"; //new price will be 125

如果您随后检查xmlDoc变量,则会使用价格为p1的{​​{1}}进行更新,以便您可以将其保存。当然,您可以使用LINQ创建泛型方法,以便更容易替换任何节点,但上面应该会想到一种方法。