2009-02-13 56 views
12

我想看看改變XML元素的值的最佳方式。最好的方法來改變C中的元素的值#

<MyXmlType> 
    <MyXmlElement>Value</MyXmlElement> 
</MyXmlType> 

什麼是最簡單和/或最好的方式來改變C#中的「價值」?

我看過XMLDocument,它會導致整個XML文檔加載到內存中。您可以使用XMLReader安全地執行此操作嗎?問題在於改變價值並將其轉化回來似乎是一個有趣的難題。

乾杯:d

回答

28

您可以使用System.Xml.Linq命名空間的東西來獲取最簡單的代碼。這會將完整的文件加載到內存中。

XDocument xdoc = XDocument.Load("file.xml"); 
var element = xdoc.Elements("MyXmlElement").Single(); 
element.Value = "foo"; 
xdoc.Save("file.xml"); 
+0

XML命名空間給了我難過,但它讓我到了我需要的地方。 謝謝,再加上linqy的東西不錯:)。 基於我提供的示例已經工作的XML。 – Spence 2009-02-13 03:29:29

2

你可以使用一個XmlReader讀取成通過泵的XmlWriter數據背出一個類和掃描讀/寫之間的元素,該值作爲必要改變。

老實說,我有點驚訝你的XML文件太大了,你擔心內存消耗......並不是說這不是問題。如果沒有更多的信息,我不能說你的假設的XML文件不是50GB,但是在很多情況下,加載足夠長的內存到內存中的操作並不像你想象的那麼重要。

+0

Base64編碼的二進制圖像:'( – Spence 2009-02-13 01:17:07

5

編輯:沒有看到你的關於XmlDocument的條款。 XmlReader就是這樣做的。你不能編輯這個類的xml文件。

你想要XmlWriter。但是,如果它仍然有用,這裏是XmlDocument的代碼。

private void changeXMLVal(string element, string value) 
{ 
    try 
    { 
     string fileLoc = "PATH_TO_XML_FILE"; 
     XmlDocument doc = new XmlDocument(); 
     doc.Load(fileLoc); 
     XmlNode node = doc.SelectSingleNode("/MyXmlType/" + element); 
     if (node != null) 
     { 
      node.InnerText = value; 
     } 
     else 
     { 
      XmlNode root = doc.DocumentElement; 
      XmlElement elem; 
      elem = doc.CreateElement(element); 
      elem.InnerText = value; 
      root.AppendChild(elem); 
     } 
     doc.Save(fileLoc); 
     doc = null; 
    } 
    catch (Exception) 
    { 
     /* 
     * Possible Exceptions: 
     * System.ArgumentException 
     * System.ArgumentNullException 
     * System.InvalidOperationException 
     * System.IO.DirectoryNotFoundException 
     * System.IO.FileNotFoundException 
     * System.IO.IOException 
     * System.IO.PathTooLongException 
     * System.NotSupportedException 
     * System.Security.SecurityException 
     * System.UnauthorizedAccessException 
     * System.UriFormatException 
     * System.Xml.XmlException 
     * System.Xml.XPath.XPathException 
     */ 
    } 
} 
+1

他特意問怎麼做*沒有*使用XmlDocument – 2009-02-13 01:14:35

+2

這確實對應於問題的標題,並幫助我。 +1 – Erix 2009-06-30 19:46:47

2

您是否想過將Linq用於XML? (如果你使用的是.NET 3.0+)

public static XElement ChangeValue(string xmlSnippet, 
    string nodeName, 
    string newValue) 
{ 
    XElement snippet = XElement.Parse(xmlSnippet); 
    if (snippet != null) 
    { 
     snippet.Element(nodeName).Value = newValue; 
    } 
    return snippet; 
} 

我猜的XElement會比XmlDocument的表現更好操作(雖然不知道),爲的XElement的基本對象是X對象,是的,它必須加載整個文件。

2

使用只讀閱讀器肯定會是最有效的方法,在這種情況下,XmlReader派生似乎是適當的,但可以肯定的是,儘管它比使用一次加載整個文件的DOM方法更有用。

XmlReader被認爲是源自Java世界的SAX XML解析器API的改進,但它已成爲業界(Microsoft之外)的事實標準。

如果你只是想快速完成工作,XmlTextReader就是爲此目的而存在的(在.NET中)。

如果你想學習一個穩定的事實標準(並且在很多編程語言中都可用),這將迫使你非常高效和優雅地編寫代碼,但它也非常靈活,然後看看SAX。 但是,除非你打算創建高度深奧的XML解析器,否則不要打擾SAX本身。有很多解析器在那裏使用SAX。

請看看這裏我關於SAX響應的SAX資源列表和真正有創造性的。NET的XML解析器想法使用的XmlTextReader爲基礎: SAX vs XmlTextReader - SAX in C#

1
using System; 
using System.Xml; 
using System.Linq; 
using System.Xml.Linq; 

namespace ReandAndWriteXML 
{ 
    class MainClass 
    { 
     public static void Main (string[] args) 
     { 
      XDocument xdoc = XDocument.Load(@"file.xml"); 
      var element = xdoc.Root.Elements("MyXmlElement").Single(); 
      element.Value = "This wasn't nearly as hard as the internet tried to make it!"; 
      xdoc.Save(@"file.xml"); 
     } 
    } 
} 

這很像本羅賓的例子,但它的作品(雖然他確實太少,現在,它已被編輯)。我甚至給你使用指令!

2

它使用一箇舊文件並創建一個具有更新值的新文件。它會拋出一個異常,如果它無法找到元素

{ 
    XDocument newSettingFile = new XDocument(settingFile); 
    //Root element 
    var newSetting = newSettingFile.Element("MyXmlType"); 
    //Update childelement with new value 
    newSetting.Element("MyXmlElement").Value = "NewValue"; 
    return newSettingFile; 
} 
1

我跑,這是10.6 K.解析XmlDocument的文檔一些測試永遠是快於LINQ查詢,約50%。

 var stopwatch2 = Stopwatch.StartNew(); 
     XmlDocument xd = new XmlDocument(); 
     xd.LoadXml(instanceXML); 
     XmlNode node = xd.SelectSingleNode("//figures/figure[@id='" + stepId + "']/properties/property[@name='" + fieldData + "']"); 
      node.InnerXml = "<![CDATA[ " + valData + " ]]>"; 
     stopwatch2.Stop(); 
     var xmlDocTicks = stopwatch2.ElapsedTicks; 

     Stopwatch stopwatch1 = Stopwatch.StartNew(); 
     XDocument doc = XDocument.Parse(instanceXML); 
     XElement prop = 
     (from el in doc.Descendants("figure") 
     where (string)el.Attribute("id") == stepId 
      select el).FirstOrDefault(); 
     prop.Value = valData; 
     stopwatch1.Stop(); 
     var linqTicks = stopwatch1.ElapsedTicks; 

的結果如下(xmlDocTicks,linqTicks):

  • RUN1:(1258,1581)
  • RUN2:(2667,3463)
  • RUN3:(1416,2626 )
  • run4:(1231,2383)
  • 平均:(1643,2513)