代码之家  ›  专栏  ›  技术社区  ›  wonea Ilya Smagin

读取、修改和写入XML的最佳方法

  •  13
  • wonea Ilya Smagin  · 技术社区  · 14 年前

    我的计划是使用我的C程序在XML文档中阅读,搜索我想要更改的特定条目,然后写出修改过的文档。但是,我已经失去了联系,因为很难区分元素,不管它们是开始还是结束使用我在文件中读取的xmltextreader。我可以接受一些建议,让我走上正轨。

    文档是一个HTML文档,所以可以想象,它非常复杂。

    我想在HTML文档中搜索一个元素ID,例如查找这个元素并更改SRC;

    <img border="0" src="bigpicture.png" width="248" height="36" alt="" id="lookforthis" />
    
    8 回复  |  直到 7 年前
        1
  •  30
  •   Jon Skeet    11 年前

    如果它实际上是有效的XML,并且很容易放在内存中,我会选择 LINQ to XML ( XDocument , XElement 等)每次。这是迄今为止我使用过的最好的XML API。它很容易形成查询,也很容易构造新的元素。

    您可以在适当的地方使用xpath,或者使用内置的axis方法( Elements() , Descendants() , Attributes() 等)。如果您能让我们知道您遇到的困难是什么,我很乐意帮助您解决如何用linq-to-xml表示它们。

    另一方面,如果这是HTML, 不是 有效的XML,您将有更困难的时间-因为XML API Generalyl希望使用有效的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");
    }
    
        2
  •  4
  •   Mark Lakata    12 年前

    您正在处理的文档是否相对较小?如果是这样,您可以使用一个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的结构,这可能会使解析代码更简单一些。

        3
  •  2
  •   Mark Lakata    12 年前

    这是我编写的一个工具,用于修改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>
    
        4
  •  1
  •   codymanix    14 年前

    如果您有适合计算机内存的较小文档,可以使用 XmlDocument . 否则你可以用 XmlReader 遍历文档。

    使用 XMLRead 可以使用以下方法查找元素类型:

    while (xml.Read()) {
       switch xml.NodeType {
         case XmlNodeType.Element:
          //Do something
         case XmlNodeType.Text:
          //Do something
         case XmlNodeType.EndElement:  
          //Do something
       }
    }
    
        5
  •  1
  •   annakata    14 年前

    对于手头的任务(阅读现有的文档,以正式的方式编写和修改),我同意 XPathDocument 穿过一个 XslCompiledTransform .

    如果您不能正式化,没有预先存在的文档,或者通常需要更多的自适应逻辑,我将使用如skeet所说的LINQ和xdocument。

    基本上,如果任务是转换,那么是XSLT;如果任务是操作,那么是LINQ。

        6
  •  1
  •   Peter J    14 年前

    我最喜欢的工具是 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');
    
        7
  •  0
  •   ngroot    14 年前

    一个相当简单的方法是创建一个新的 XmlDocument 然后使用 Load() 方法来填充它。一旦你拿到文件,你就可以使用 CreateNavigator() 得到一个 XPathNavigator 对象,可用于查找和更改文档中的元素。最后,您可以使用 Save() 方法在 XML文档 把修改过的文件写回去。

        8
  •  -1
  •   Nathan Wheeler    14 年前

    从阅读 Xml namespace on the MSDN . 如果你有更具体的问题,把它们贴在这里…