【问题标题】:Most efficient way to replace text in xml stream替换xml流中文本的最有效方法
【发布时间】:2015-11-05 09:18:00
【问题描述】:

我有大量需要“清理”的 XML 数据。 Xml 看起来像这样:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
    <w:body>
        <w:p>       
                    <w:t>F_ck</w:t>
            <!-- -->
                <w:t>F_ck</w:t>
            <!-- -->
                            <w:t>F_ck</w:t>
        </w:p>
    </w:body>
</w:document>

我想用值“F_ck”标识&lt;w:t&gt;-元素,并用其他值替换该值。我需要清理的元素会分散在整个文档中。

我需要代码尽可能快地运行并且内存占用尽可能小,所以我不愿意使用我在这里和其他地方找到的XDocument (DOM) 方法。

数据作为包含 Xml 数据的流提供给我,我的直觉告诉我我需要 XmlTextReaderXmlTextWriter

我最初的想法是做一个 SAX 模式,只向前运行 Xml 数据并将其“管道”到XmlTextWriter,但我找不到这样做的智能方法。

我写了这段代码:

var reader = new StringReader(content);
var xmltextReader = new XmlTextReader(reader);
var memStream = new MemoryStream();
var xmlWriter = new XmlTextWriter(memStream, Encoding.UTF8);

while (xmltextReader.Read())
{
    if (xmltextReader.Name == "w:t")
    {
        //xmlWriter.WriteRaw("blah");
    }
    else
    {
        xmlWriter.WriteRaw(xmltextReader.Value);
    }
}

上面的代码只取元素声明等的值,所以没有括号或任何东西。我意识到我可以根据NodeType 编写专门执行.WriteElement().WriteEndElement() 等的代码,但我担心这很快就会一团糟。

所以问题是:

我如何 - 以一种很好的方式 - 将从 XmlTextReader 读取的 xml 数据通过管道传输到 XmlTextWriter,同时仍然能够在管道传输时操作数据?

【问题讨论】:

  • “w”称为前缀,由命名空间定义:xmlns:w="schemas.openxmlformats.org/wordprocessingml/2006/main"。你想做什么?不需要清理文档即可反序列化。
  • @jdweng 我知道命名空间是什么:-)。我不是要解决反序列化问题。我正在尝试找到替换 Xml 数据中某些元素的值的“最佳”方法。
  • 使用 XDocument (xml linq)。查找标签,然后简单地替换值。
  • @jdweng 是的,我会看看我是否可以让它工作,但正如我在 OP 中所写的那样,由于它的内存占用,我不愿意使用 XDocument。因此,我将帖子保持打开状态,希望能获得有关使用 XmlTextReader/Writer 的帮助 :-)
  • 如果您关心速度或内存,请尝试以下网站的代码。如果您将 xml 文件下载到本地磁盘,它是一个 6MByte XML 文件,可以在几秒钟内运行。 stackoverflow.com/questions/33506815/…

标签: c# xml memory xmltextreader xmltextwriter


【解决方案1】:

试试这个

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

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string xml =
                "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" +
                "<w:document xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\">" +
                    "<w:body>" +
                        "<w:p>" +
                                    "<w:t>F_ck</w:t>" +
                            "<!-- -->" +
                                "<w:t>F_ck</w:t>" +
                            "<!-- -->" +
                                            "<w:t>F_ck</w:t>" +
                        "</w:p>" +
                    "</w:body>" +
                "</w:document>";

            XDocument doc = XDocument.Parse(xml);
            XElement document = (XElement)doc.FirstNode;
            XNamespace ns_w = document.GetNamespaceOfPrefix("w");
            List<XElement> ts = doc.Descendants(ns_w + "t").ToList();
            foreach (XElement t in ts)
            {
                t.Value = "abc";
            }

        }
    }
}
​

【讨论】:

  • 为什么大家都喜欢 XDocument?它非常缓慢且占用大量内存
  • 是不是比 XmlDocument 好很多? XDocument 指令较少,提取标签更容易。
猜你喜欢
  • 2011-02-19
  • 2016-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-26
  • 2016-06-27
相关资源
最近更新 更多