XmlReader - I need to edit an element and produce a new one

前端 未结 5 2115
花落未央
花落未央 2020-12-20 15:54

I am overriding a method which has an XmlReader being passed in, I need to find a specific element, add an attribute and then either create a new XmlReader or just replace t

5条回答
  •  借酒劲吻你
    2020-12-20 16:32

    XmlReader/Writer are sequential access streams. You will have to read in on one end, process the stream how you want, and write it out the other end. The advantage is that you don't need to read the whole thing into memory and build a DOM, which is what you'd get with any XmlDocument-based approach.

    This method should get you started:

    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;
                }
            }
        }
    }
    

    This is not quite as clean as deriving your own XmlWriter, but I find that it's much easier.

    [EDIT]

    An example of how you would open two streams at once might be something like this:

    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);
      }
    }
    

提交回复
热议问题