簡體   English   中英

讀取,修改和寫入XML的最佳方法

[英]Best way to read, modify, and write XML

我的計划是使用C#程序讀取XML文檔,搜索要更改的特定條目,然后寫出修改后的文檔。 但是,我變得困惑不解,因為很難區分元素,無論它們是使用我用來讀取文件的XmlTextReader開頭還是結尾。 我可以提供一些建議,使我走上正確的道路。

該文檔是HTML文檔,因此可以想象,它非常復雜。

我想在HTML文檔中搜索元素ID,因此例如查找並更改src。

<img border="0" src="bigpicture.png" width="248" height="36" alt="" id="lookforthis" />

如果它實際上是有效的XML,並且很容易裝入內存,那么我每次都會選擇LINQ to XMLXDocumentXElement等)。 到目前為止,這是我使用過的最好的XML API。 形成查詢很容易,構造新元素也很容易。

您可以在適當的地方使用XPath,也可以使用內置的軸方法( Elements()Descendants()Attributes()等)。 如果您可以讓我們知道您遇到什么困難,我很樂於幫助您確定如何用LINQ to XML來表達它們。

另一方面,如果這是不是有效XML的HTML,那么您將面臨更多困難-因為XML通用語法希望可以與有效XML文檔一起使用。 您當然可以先使用HTMLTidy ,但這可能會產生不良影響。

對於您的特定示例:

XDocument doc = XDocument.Load("file.xml");
foreach (var img in doc.Descendants("img"))
{
    // src will be null if the attribute is missing
    string src = (string) img.Attribute("src");
    img.SetAttributeValue("src", src + "with-changes");
}

您正在處理的文件是否相對較小? 如果是這樣,則可以使用XmlDocument對象將它們加載到內存中,對其進行修改,然后將所做的更改寫回。

XmlDocument doc = new XmlDocument();
doc.Load("path_to_input_file");
// Make changes to the document.
using(XmlTextWriter xtw = new XmlTextWriter("path_to_output_file", Encoding.UTF8)) {
  xtw.Formatting = Formatting.Indented; // optional, if you want it to look nice
  doc.WriteContentTo(xtw);
}

根據輸入XML的結構,這可以使您的解析代碼更簡單。

這是我編寫的用於修改IAR EWARM項目(ewp)文件的工具,為該項目添加了鏈接器定義。 在命令行中,使用2個參數(輸入和輸出文件名(* .ewp))運行它。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Xml;

    namespace ewp_tool
    {
        class Program
        {
            static void Main(string[] args)
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(args[0]);

                XmlNodeList list = doc.SelectNodes("/project/configuration[name='Debug']/settings[name='ILINK']/data/option[name='IlinkConfigDefines']/state");
                foreach(XmlElement x in list) {
                    x.InnerText = "MAIN_APP=1";
                }

                using (XmlTextWriter xtw = new XmlTextWriter(args[1], Encoding.UTF8))
                {
                    //xtw.Formatting = Formatting.Indented; // leave this out, it breaks EWP!
                    doc.WriteContentTo(xtw);
                }
            }
        }
    }

XML的結構如下所示

    <U+FEFF><?xml version="1.0" encoding="iso-8859-1"?>
    <project>
      <fileVersion>2</fileVersion>
      <configuration>
        <name>Debug</name>
        <toolchain>
          <name>ARM</name>
        </toolchain>
        <debug>1</debug>

         ...

        <settings>
          <name>ILINK</name>
          <archiveVersion>0</archiveVersion>
          <data>

            ...

            <option>
              <name>IlinkConfigDefines</name>
              <state>MAIN_APP=0</state>
            </option>

如果您有較小的文檔適合計算機內存,則可以使用XmlDocument 否則,您可以使用XmlReader遍歷文檔。

使用XmlReader您可以使用以下XmlReader找出元素類型:

while (xml.Read()) {
   switch xml.NodeType {
     case XmlNodeType.Element:
      //Do something
     case XmlNodeType.Text:
      //Do something
     case XmlNodeType.EndElement:  
      //Do something
   }
}

對於手頭的任務-(以正式的方式閱讀現有文檔,編寫和修改),我將通過XslCompiledTransform運行XPathDocument

在無法形式化,沒有預先存在的文檔或通常需要更多自適應邏輯的地方,我會像Skeet所說的那樣使用LINQ和XDocument。

基本上,如果任務是轉換,則為XSLT;如果任務是操縱,則為LINQ。

對於此類事情,我最喜歡的工具是HtmlAgilityPack 我用它將復雜的HTML文檔解析為LINQ可查詢的集合。 它是用於查詢和解析HTML(通常不是有效的XML)的極其有用的工具。

對於您的問題,代碼如下所示:

var htmlDoc = HtmlAgilityPack.LoadDocument(stringOfHtml);
var images = htmlDoc.DocumentNode.SelectNodes("//img[id=lookforthis]");

if(images != null)
{
  foreach (HtmlNode node in images)  
  {  
      node.Attributes.Append("alt", "added an alt to lookforthis images.");  
  }  
}

htmlDoc.Save('output.html');

一種相當簡單的方法是創建一個新的XmlDocument ,然后使用Load()方法填充它。 獲取文檔后,可以使用CreateNavigator()獲取XPathNavigator對象,該對象可用於查找和更改文檔中的元素。 最后,您可以使用XmlDocument上的Save()方法將更改后的文檔寫回。

只需閱讀MSDN上Xml命名空間的文檔即可。 然后,如果您有更具體的問題,請在此處發布...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM