更改XML中最后一个属性的值c#

时间:2010-09-10 07:26:05

标签: c# xml

我正在处理一堆XML,这些XML都共享一个包含字符串“name”的属性。以下代码选择其中包含字符串“name”的属性,并为其指定新值。

        public void updateXmlFile(string strFileName)
    {
        try
        {
            //Load the Document
            XmlDocument doc = new XmlDocument();
            doc.Load(strFileName);
            //Set the changed Value
            string newValue = GetUniqueKey();
            //Select all nodes in the XML then choose from them
            //the first node that contain string "name" in it
            XmlNodeList list = doc.SelectNodes("//@*");
            XmlNode filteredNode = list.Cast<XmlNode>()
                .First(item => item.Name.ToLower().Contains("name"));
            //Assign the newValue to the value of the node
            filteredNode.Value = newValue;

            doc.Save(strFileName);
        }
        catch (XmlException xex) { Console.WriteLine(xex); }
    }

现在添加了一个新的XML,它们中没有字符串“name”,因此我决定简单地修改最后一个属性,而不是修改其中的字符串“name”。第一个)

有人可以告诉我该怎么做吗?

修改

以下是我的XML

的示例
<?xml version="1.0" encoding="utf-8"?>
<CO_CallSignLists Version="24" ModDttm="2010-09-13T06:45:38.873" ModUser="EUADEV\SARE100" ModuleOwner="EUADEVS06\SS2008" CreateDttm="2009-11-05T10:19:31.583" CreateUser="EUADEV\A003893">
  <CoCallSignLists DataclassId="E3FC5E2D-FE84-492D-AD94-3ACCED870714" EntityId="E3FC5E2D-FE84-492D-AD94-3ACCED870714" MissionID="4CF71AB2-0D92-DE11-B5D1-000C46F3773D" BroadcastType="S" DeputyInSpecialList="1" SunSpots="1537634cb70c6d80">
    <CoCallSigns EntityId="DEBF1DDB-3C92-DE11-A280-000C46F377C4" CmdID="C45F3EF1-1292-DE11-B5D1-000C46F3773D" ModuleID="6CB497F3-AD63-43F1-ACAE-2C5C3B1D7F61" ListType="HS" Name="Reda Sabassi" Broadcast="INTO" PhysicalAddress="37" IsGS="1" HCId="0" CommonGeoPos="1" GeoLat="0.0000000" GeoLong="0.0000000">
      <CoRadios EntityId="E1BF1DDB-3C92-DE11-A280-000C46F377C4" RadioType="HF" />
    </CoCallSigns>
  </CoCallSignLists>
</CO_CallSignLists>

@Alex:您注意到“SunSpots”属性(第一个子元素中的最后一个属性)已成功更改。但现在,当我想将XML加载回数据库时,它会给我一个错误

这是修改后的代码

    public void updateXmlFile(string strFileName)
    {
        try
        {
            XDocument doc = XDocument.Load(strFileName);

            XAttribute l_attr_1 = (doc.Elements().First().Elements().First().Attributes().Last());
            l_attr_1.Value = GetUniqueKey();

            Console.WriteLine("Name: {0}  Value:{1}", l_attr_1.Name, l_attr_1.Value);

            doc.Save(strFileName);
        }
        catch (XmlException xex) { Console.WriteLine(xex); }
    }

我正在考虑制作一个if语句来检查XML是否有一个包含字符串“name”的属性(因为我的大部分XML都有一个包含其中名称的属性),如果它确实改变了属性的值如果没有找到最后一个属性并改变它..不是最好的解决方案,只是把它扔出去

4 个答案:

答案 0 :(得分:1)

我没有对此进行过测试,但您应该可以在XPath表达式中完成所有这些操作。像这样:

//@*[contains(node-name(.), 'name')][last()]

这将只返回名称中包含字符串name的最后一个属性。

如果您只想要最后一个属性,无论其名称如何,请使用:

//@*[last()]

答案 1 :(得分:1)

然后肯定使用Linq到XML。 例如:

using System.Xml.Linq;

string xml = @"<?xml version=""1.0"" encoding=""utf-8""?>
<Commands Version=""439""  CreateUser=""Reda"">
  <CmCommands DataclassId=""57067ca8-ef96-4d2e-a085-6bd7e8b24126"" OrderName = ""Tea"" Remark=""Black"">
    <CmExecutions EntityId=""A9A5B0F2-6AB4-4619-9106-B0F85F86EE01"" Lock=""n"" />
  </CmCommands>
</Commands>";

XDocument x = XDocument.Parse(xml);

Debug.Print(x.Elements().First().Elements().First().Attributes().Last().Value);
//                 Commands ^      CmCommands ^             Remark ^

即,逐字逐句,第一个元素的第一个子元素的最后一个属性。

您还可以查询元素/属性名称,例如:

Debug.Print(x.Descendants(XName.Get("CmCommands", "")).First().Attribute(XName.Get("Remark", "")).Value);

当然,你可以使用所有的Linq善良,如Where,Select,Any,All等。

注意:如果合适,请将XDocument.Parse替换为XDocument.Load等。

答案 2 :(得分:0)

查看班级XmlAttributeCollection。您可以通过读取属性XmlNode的属性来获取此集合。只需通过索引获取最后一个。

答案 3 :(得分:0)

使用这样的扩展方法代替.First()

public static T LastOrDefault<T>(this IEnumerable<T> list)
{
  T val = null;
  foreach(T item in list)
  {
     val = item;
  }

  return val;
}