【问题标题】:Modifying Existing XML Content in C#在 C# 中修改现有 XML 内容
【发布时间】:2023-03-03 10:09:01
【问题描述】:

我发现了一些关于这个主题的例子。一些例子给出了用SelectNodes()SelectSingleNode()修改属性的方法,还有一些例子给出了用someElement.SetAttribute("attribute-name", "new value");修改属性的方法

但是如果我只使用XpathNodeItterator it,我仍然对如何建立关系感到困惑?

假设我定义如下,

System.Xml.XPath.XPathDocument doc = new XPathDocument(xmlFile);
System.Xml.XPath.XPathNavigator nav = doc.CreateNavigator();
System.Xml.XPath.XPathNodeIterator it;

it = nav.Select("/Equipment/Items/SubItmes");
while (it.MoveNext())
{
   name = it.Current.GetAttribute("name ", it.Current.NamespaceURI);
   int vidFromXML = int.Parse(it.Current.GetAttribute("vid", it.Current.NamespaceURI));
   if (vidFromXML = vid)
   { 
    // How can I find the relation between it and element and node? I want to modify name attribute value. 
   }
}

it.setAttribute(name, "newValue")这样的方法吗?

【问题讨论】:

    标签: c# xml c#-2.0 setattribute selectnodes


    【解决方案1】:

    我写了一个扩展方法,它为任何XPathNavigator 提供了一个SetAttribute 方法:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Xml;
    using System.Xml.XPath;
    
    namespace My.Shared.Utilities {
        public static class XmlExtensions {
            public static void SetAttribute(this XPathNavigator nav, string localName, string namespaceURI, string value) {
                if (!nav.MoveToAttribute(localName, namespaceURI)) {
                    throw new XmlException("Couldn't find attribute '" + localName + "'.");
                }
                nav.SetValue(value);
                nav.MoveToParent();
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      来自MSDN:“XPathNavigator 对象是从实现 IXPathNavigable 接口的类创建的,例如 XPathDocument 和 XmlDocument 类。由 XPathDocument 对象创建的 XPathNavigator 对象是只读的,而 XPathNavigator 对象可以编辑由 XmlDocument 对象创建的对象。XPathNavigator 对象的只读或可编辑状态是使用 XPathNavigator 类的 CanEdit 属性确定的。"

      所以,如果要设置属性,首先必须使用 XmlDocument,而不是 XPathDocument。

      here 显示了如何使用 XPathNavigator 使用 XmlDocument 的 CreateNavigator 方法修改 XML 数据的示例。

      您将从示例中看到,在您的 it.Current 对象上有一个方法 SetValue

      以下是您对代码的处理方式,稍作修改:

              int vid = 2;
              var doc = new XmlDocument();
              doc.LoadXml("<Equipment><Items><SubItems  vid=\"1\" name=\"Foo\"/><SubItems vid=\"2\" name=\"Bar\"/></Items></Equipment>");
              var nav = doc.CreateNavigator();
      
              foreach (XPathNavigator it in nav.Select("/Equipment/Items/SubItems"))
              {
                  if(it.MoveToAttribute("vid", it.NamespaceURI)) {
                      int vidFromXML = int.Parse(it.Value);                    
                      if (vidFromXML == vid)
                      {
                          // if(it.MoveToNextAttribute() ... or be more explicit like the following:
      
                          if (it.MoveToParent() && it.MoveToAttribute("name", it.NamespaceURI))
                          {
                              it.SetValue("Two");
                          } else {
                              throw new XmlException("The name attribute was not found.");
                          }                
                      }
                  } else {
                          throw new XmlException("The vid attribute was not found.");
                  }
              }
      

      【讨论】:

      • 感谢您的意见。我研究了 MSDN 教程。我发现'SetValue'的方法是用来更新元素值,而不是属性值。可以尝试但失败了。我需要找到更新属性值的方法。
      • 我现在找到了您的详细更新。介绍了it.MoveToAttribute()。我现在就试试。谢谢。
      • .NET 2.0 中没有var。当我将字符串类型值传递给name 时,我无法使用int.Parse(name)。抛出 输入字符串的格式不正确。。我该如何解决?
      • 我仍然认为微软认为包含 GetAttributeCreateAttribute 方法而不是 SetAttribute 方法是很奇怪的,因为 SetAttribute 的功能很有帮助并且确实可以实现使用扩展方法。
      • @RichardHein 但它没有只读语义 - 有一个 SetValue 方法和一个 CreateAttribute 方法。