在xml流中替换文本的最有效方法

时间:2015-11-05 09:18:01

标签: c# xml memory xmltextreader xmltextwriter

我需要“清理”大量的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”的<w:t> - 元素,并用其他内容替换该值。我需要清理的元素将分散在整个文档中。

我需要代码尽可能快地运行并且内存占用尽可能小,所以我不愿意使用我在这里和其他地方找到的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);
    }
}

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

所以问题是:

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

1 个答案:

答案 0 :(得分:0)

试试这个

&#13;
&#13;
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";
            }

        }
    }
}
​
&#13;
&#13;
&#13;