XmlReader - 我需要编辑一个元素并生成一个新元素

Phi*_*ffy 8 c# xml xmlreader c#-4.0

我重写了一个传入XmlReader的方法,我需要找到一个特定的元素,添加一个属性,然后创建一个新的XmlReader或者用修改后的内容替换现有的XmlReader.我正在使用C#4.0

我已经使用XElement(Linq)进行了调查,但我似乎无法操纵现有元素并添加属性和值.

我知道XmlWriter有WriteAttributeString,这将是太棒了但是我不知道它是如何组合在一起的

我希望能够做到这样的事情---这是伪代码!

public XmlReader DoSomethingWonderful(XmlReader reader)
{
   Element element = reader.GetElement("Test");
   element.SetAttribute("TestAttribute","This is a test");
   reader.UpdateElement(element);
   return reader;
}
Run Code Online (Sandbox Code Playgroud)

Ale*_*x J 13

XmlReader/Writer是顺序访问流.您必须在一端读入,按照您想要的方式处理流,并将其写出另一端.优点是您不需要将整个内容读入内存并构建DOM,这是您使用任何基于XmlDocument的方法所获得的.

这个方法应该让你开始:

private static void PostProcess(Stream inStream, Stream outStream)
{
    var settings = new XmlWriterSettings() { Indent = true, IndentChars = " " };

    using (var reader = XmlReader.Create(inStream))
    using (var writer = XmlWriter.Create(outStream, settings)) {
        while (reader.Read()) {
            switch (reader.NodeType) {
                case XmlNodeType.Element:
                    writer.WriteStartElement(reader.Prefix, reader.Name, reader.NamespaceURI);
                    writer.WriteAttributes(reader, true);

                    //
                    // check if this is the node you want, inject attributes here.
                    //

                    if (reader.IsEmptyElement) {
                        writer.WriteEndElement();
                    }
                    break;

                case XmlNodeType.Text:
                    writer.WriteString(reader.Value);
                    break;

                case XmlNodeType.EndElement:
                    writer.WriteFullEndElement();
                    break;

                case XmlNodeType.XmlDeclaration:
                case XmlNodeType.ProcessingInstruction:
                    writer.WriteProcessingInstruction(reader.Name, reader.Value);
                    break;

                case XmlNodeType.SignificantWhitespace:
                    writer.WriteWhitespace(reader.Value);
                    break;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这不像派生自己的XmlWriter那么干净,但我发现它更容易.

[编辑]

如何一次打开两个流的示例可能是这样的:

using (FileStream readStream = new FileStream(@"c:\myFile.xml", FileMode.OpenOrCreate, FileAccess.Read, FileShare.Write)) {
  using (FileStream writeStream = new FileStream(@"c:\myFile.xml", FileMode.OpenOrCreate, FileAccess.Write)) {
    PostProcess(readStream, writeStream);
  }
}
Run Code Online (Sandbox Code Playgroud)