2009-02-13 33 views
12

Tôi đang cố gắng xem xét cách tốt nhất để thay đổi giá trị của một phần tử trong XML.Cách tốt nhất để thay đổi giá trị của một phần tử trong C#

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

Cách dễ nhất và/hoặc cách tốt nhất để thay đổi "Giá trị" trong C# là gì?

Tôi đã xem XMLDocument và nó sẽ làm cho tải toàn bộ tài liệu XML vào bộ nhớ. Bạn có thể làm điều đó một cách an toàn với XMLReader không. Vấn đề đang thay đổi giá trị và phát ra nó có vẻ như một câu hỏi hóc búa thú vị.

Chúc mừng: D

Trả lời

28

Bạn có thể sử dụng công cụ không gian tên System.Xml.Linq để dễ đọc nhất. Thao tác này sẽ tải toàn bộ tệp vào bộ nhớ.

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

Không gian tên XML khiến tôi đau buồn, nhưng nó đã đưa tôi đến nơi tôi cần. Cảm ơn, cộng với công cụ linqy là tốt đẹp :). Dựa trên xml tôi đã cung cấp ví dụ của bạn đã hoạt động. – Spence

+0

Điều này không hoạt động ... XDocument.Parse dự kiến ​​một chuỗi XML ... –

2

Bạn có thể sử dụng một XmlReader để đọc vào một lớp học mà bơm dữ liệu trở lại thông qua một XmlWriter và quét cho các phần tử giữa đọc/ghi, thay đổi giá trị khi cần thiết.

Thành thật mà nói, tôi hơi ngạc nhiên khi tệp XML của bạn quá lớn đến nỗi bạn lo lắng về mức tiêu thụ bộ nhớ ... không nói nó không bao giờ là vấn đề. Nếu không có thêm thông tin, tôi không thể nói rằng tệp XML giả định của bạn không phải là 50GB, nhưng trong nhiều trường hợp tải các tệp có vẻ lớn vào bộ nhớ đủ lâu để thao tác không phải là một thỏa thuận lớn như bạn nghĩ.

+0

Hình ảnh nhị phân được mã hóa Base64: '( – Spence

5

EDIT: không thấy mệnh đề của bạn về XmlDocument. XmlReader làm điều đó. Bạn không thể chỉnh sửa các tệp xml với lớp này.

Bạn muốn XmlWriter. Tuy nhiên, trong trường hợp nó vẫn hữu ích, đây là mã cho 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

Anh ấy đặc biệt hỏi cách thực hiện * mà không * bằng XmlDocument –

+2

Điều này tương ứng với tiêu đề của câu hỏi và đã giúp tôi. +1 – Erix

2

Bạn đã nghĩ đến việc sử dụng LINQ to XML chưa? (Nếu bạn đang sử dụng 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; 
} 

Tôi đoán XElement sẽ hoạt động tốt hơn XmlDocument (mặc dù điều không chắc chắn), đối tượng cơ sở cho XElement là XObject, và có, nó sẽ phải tải toàn bộ tài liệu.

2

Sử dụng trình đọc chỉ có khả năng là cách tiếp cận hiệu quả nhất, trong trường hợp đó dẫn xuất XmlReader có vẻ phù hợp, để chắc chắn, mặc dù nó vẫn hoạt động tốt hơn sử dụng phương pháp DOM tải toàn bộ tệp cùng một lúc.

XmlReader được cho là một cải tiến đối với API phân tích cú pháp XML SAX có nguồn gốc trong thế giới Java, nhưng đã trở thành tiêu chuẩn thực tế trong ngành (ngoài Microsoft).

Nếu bạn chỉ muốn hoàn thành công việc một cách nhanh chóng, XmlTextReader tồn tại cho mục đích đó (trong .NET).

Nếu bạn muốn học một chuẩn thực tế ổn định (và cũng có sẵn bằng nhiều ngôn ngữ lập trình) và sẽ buộc bạn phải viết mã rất hiệu quả và thanh lịch, nhưng cũng cực kỳ linh hoạt, hãy xem SAX. Tuy nhiên, đừng bận tâm với SAX, trừ khi bạn định tạo các trình phân tích cú pháp XML rất bí truyền. Có rất nhiều trình phân tích cú pháp ngoài đó sử dụng SAX dưới bìa.

Vui lòng xem trả lời câu trả lời của tôi về SAX tại đây để biết danh sách các tài nguyên SAX và thực sự sáng tạo .NET phân tích cú pháp XML ý tưởng sử dụng XmlTextReader như nền tảng của nó: 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"); 
     } 
    } 
} 

Đây là giống như ví dụ Bến Robin, ngoại trừ nó hoạt động (mặc dù mình không quá, bây giờ mà nó đã được chỉnh sửa). Và tôi thậm chí còn đưa cho bạn các chỉ thị sử dụng!

+1

Vấn đề là tệp XML có dung lượng trên 100MB và tôi phải thực hiện việc này thường xuyên. Vì vậy, nếu tôi có thể tránh sử dụng lớp XDocument thì tài liệu có thể được truyền vào và ra khi tôi thay đổi nó, mà không yêu cầu tải đầy đủ vào bộ nhớ. – Spence

+0

Thật không may tôi không thể giúp bạn ở đó ... Tôi chỉ đang học những thứ này bản thân mình. Tôi chỉ bị làm phiền bởi ví dụ không hiệu quả khi tôi mới đến đây từ Google, vì vậy tôi cảm thấy cần phải đăng một bài đăng trên đây là một phiên bản làm việc. – Dekker

2

Điều này sử dụng tệp cũ và tạo tệp mới có giá trị được cập nhật. Nó sẽ ném một ngoại lệ nếu nó không thể tìm ra nguyên tố

{ 
    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

Tôi chạy một số xét nghiệm trên một tài liệu đó là 10,6 K. Các phân tích cú pháp XmlDocument luôn đi ra nhanh hơn so với truy vấn LINQ, khoảng 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; 

Kết quả như sau (xmlDocTicks, linqTicks):

  • run1: (1258,1581)
  • run2: (2667,3463)
  • run3: (1416,2626)
  • run4: (1231,2383)
  • trung bình: (1643,2513)
Các vấn đề liên quan