【问题标题】:Best way to read, modify, and write XML读取、修改和编写 XML 的最佳方式
【发布时间】:2017-11-08 01:10:34
【问题描述】:

我的计划是使用我的 C# 程序读入一个 XML 文档,搜索我想要更改的特定条目,然后写出修改后的文档。但是,我已经陷入困境,因为很难区分元素,无论它们是使用我用来读取文件的 XmlTextReader 开始还是结束。我可以通过一些建议让我走上正轨。

文档是 HTML 文档,可以想象,它相当复杂。

我想在 HTML 文档中搜索一个元素 id,例如查找它并更改 src;

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

【问题讨论】:

    标签: c# xml


    【解决方案1】:

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

    您可以在合适的地方使用 XPath,或内置的轴方法(Elements()Descendants()Attributes() 等)。如果您可以让我们知道您遇到了哪些具体问题,我很乐意帮助您了解如何在 LINQ to XML 中表达它们。

    另一方面,如果这是 不是有效 XML 的 HTML,那么您将遇到更困难的情况 - 因为 XML APIs 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");
    }
    

    【讨论】:

    • 我非常同意!我有几个较旧的应用程序,我不得不通过解析等艰难的方式来完成,而 L2X 使它变得更加简单和强大。
    • Jon,您可能会发现 HtmlAgilityPack 非常有用,您可以在肮脏的真实 HTML 上使用类似于 XDocument 的 API,而不用担心有效的 XML。
    • @Peter:幸运的是,我很少需要使用肮脏的 HTML——我发现自己更频繁地使用真正的 XML。不过我会记住的。
    【解决方案2】:

    您正在处理的文档是否相对较小?如果是这样,您可以使用 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】:

      这是我为修改 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】:

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

        使用XmlReader,您可以使用以下方法找出元素类型:

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

        【讨论】:

          【解决方案5】:

          对于手头的任务 - (阅读现有文档、编写和以正式方式修改)我会使用 XPathDocument 运行 XslCompiledTransform

          如果您无法形式化、没有预先存在的文档或通常需要更多自适应逻辑,我会像 Skeet 所说的那样使用 LINQ 和 XDocument。

          如果任务是转换,那么 XSLT,如果任务是操作,那么 LINQ。

          【讨论】:

            【解决方案6】:

            我最喜欢的工具是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】:

              一种相当简单的方法是创建一个新的XmlDocument,然后使用Load() 方法填充它。获得文档后,您可以使用CreateNavigator() 获取XPathNavigator 对象,您可以使用该对象来查找和更改文档中的元素。最后,您可以使用XmlDocument 上的Save() 方法将更改的文档写回。

              【讨论】:

                【解决方案8】:

                首先阅读Xml namespace on the MSDN 的文档。然后,如果您有更具体的问题,请在此处发布...

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2012-01-04
                  • 2011-07-08
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多