2010-09-10 63 views
0

我正在研究一堆XML,它们共享一个包含字符串“name”的属性。以下代码选择包含字符串“name”的属性并为其分配一个新值。更改XML c中最后一个属性的值#

 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”属性,我决定只需修改最后一个属性不管是什么它是(不是第一个)

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

编辑

这里是我的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的例子:你注意到,“黑子”属性(在第一个子元素最后一个属性)变更成功。但现在当我想加载XML回DB它给了我一个错误

下面是修改代码

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); } 
    } 

我在想,如果制造的statment其中检查,如果XML有一个属性,它包含字符串“名称”(因为我的大多数XML都有一个属性,其中包含名称),如果它确实更改属性的值,如果不寻找最后的属性,并改变它..不是最好的解决方案,但只是抛出它那里

+0

您使用的是什么版本的运行时?从3.5开始(我认为)你可以使用Linq到XML,在这种情况下可以更容易地完成这样的事情。 – 2010-09-10 12:44:53

+0

@Alex:它是3.5我按照Daniel的建议尝试了XPath,但它修改了错误的属性(CreateUser)我想修改第一个子元素的最后一个属性(本例中为'备注') – Reda 2010-09-10 13:34:07

+0

继续编辑...一般来说,你应该用等价值替换值以避免错误,所以是的,你应该以某种方式区分不同的属性。但是按照名称来做这件事似乎是一种非常脆弱的解决方案 - 实际上,您使用的整个技术看起来像是一种脆弱的解决方案,所以我自然倾向于不喜欢它。不知道还有什么要说...通常(如果我受限于这种技术)我会阅读表架构,并确保通过检查类型来生成正确的替换。这完全取决于您的具体要求和限制。 – 2010-09-13 09:30:09

回答

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的善良喜欢的地方,选择,任何,所有等

注意:如果适当,用XDocument.Load替换XDocument.Parse。

+0

thx Alex它的工作原理:)现在只有那个问题,我有一些XML有Last属性作为smallint类型,不能作为字符串存储在数据库中..有关如何修改这些属性的任何想法? – Reda 2010-09-13 07:48:32

+0

那么,默认情况下,XML中的所有值都是字符串,并且不会自动转换;您需要手动转换(例如'int.Parse(value)')或将整个XML树转换为对象;如果您使用XML中的大部分值,那绝对是一种可行的方式,请告诉我,如果您需要更多帮助,我会编辑我的答案。 – 2010-09-13 08:14:06

+0

这个问题并没有改变属性的值,而是将它保存回DB中。值被成功修改,但是当我想将它存储回数据库时,它给了我一个错误(我修改的所有XML都是数据库表和行 – Reda 2010-09-13 08:25:33

0

看看类XmlAttributeCollection。您可以通过读取XmlNode的属性来获取此集合。只要索引得到最后一个。

0

相反的.First(),使用扩展方法是这样的:

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

    return val; 
} 
1

我没有测试这一点,但你应该能够做到这一切的XPath表达式。事情是这样的:

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

这将在其名称中带有字符串name只返回最后一个属性的任何地方。

如果你只是想最后一个属性,不论它的名字,用这个:

//@*[last()] 
+0

这工作得很好。但是现在我想知道第一个孩子的最后一个属性。我将在主Post中添加一个我的XML示例,您的代码更改了我想要更改Ony的CreatUser属性Remark属性 – Reda 2010-09-10 09:30:43