11

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

5 に答える 5

14

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

これは、独自のXmlWriterを導出するほどクリーンではありませんが、はるかに簡単であることがわかりました。

[編集]

一度に2つのストリームを開く方法の例は、次のようになります。

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);
  }
}
于 2010-02-19T12:35:44.083 に答える
2

次のダクトテープコーディングを使用して修正しました

    public XmlReader FixUpReader(XmlReader reader)
    {
       reader.MoveToContent();

        string xml = reader.ReadOuterXml();

        string dslVersion = GetDSLVersion();
        string Id = GetID();

        string processedValue = string.Format("<ExampleElement dslVersion=\"{1}\" Id=\"{2}\" ", dslVersion, Id);
        xml = xml.Replace("<ExampleElement ", processedValue);
        MemoryStream ms = new MemoryStream(System.Text.Encoding.ASCII.GetBytes(xml));
        XmlReaderSettings settings = new XmlReaderSettings();

        XmlReader myReader = XmlReader.Create(ms);
        myReader.MoveToContent();
        return myReader;
    }

私はこのようにそれをすることに対して汚い感じがします、しかしそれは働いています…。

于 2009-10-01T10:59:37.780 に答える
1

これを簡単に行うことはできませんXmlReader。少なくとも、リーダーからXMLドキュメント全体を読み取り、それをいじってXmlReader、結果から新しいドキュメントを作成する必要があります。それは、しかし、使用することの多くのポイント、XmlReaderつまり大きなドキュメントをストリーミングする機能を打ち負かします。

ほとんどのメソッド呼び出しを既存のリーダーに転送し、必要に応じてそれらをインターセプトして属性などを追加することで派生する可能性がありますが、コードは非常に複雑で壊れやすいと思われます。XmlReader

于 2009-10-01T07:54:40.947 に答える
1

むしろ、xmlをXmlDocumentオブジェクトにロードし、Attributesコレクションを使用して値を変更し、Saveメソッドを呼び出してこの値を更新したいと思います。以下のコードは私のために働きます。

 public static void WriteElementValue ( string sName, string element, string value)
 {
  try
  {
    var node = String.Format("//elements/element[@name='{0}']", sName);
    var doc = new XmlDocument { PreserveWhitespace = true };
    doc.Load(configurationFileName);

    var nodeObject = doc.SelectSingleNode(node);

     if (nodeObject == null)
         throw new XmlException(String.Format("{0} path does not found any matching 
         node", node));

    var elementObject = nodeObject[element];

    if (elementObject != null)
    {
       elementObject.Attributes["value"].Value = value;
    }

    doc.Save(configurationFileName);
}
catch (Exception ex)
{
   throw new ExitLevelException(ex, false);
}

}

また、XmlWriterまたはXmlSerializerを使用すると、空白が正しく保存されないことも確認しました。これは、煩わしい場合があります。

于 2010-02-19T11:39:30.220 に答える
-2
        string newvalue = "10";
        string presentvalue = "";
        string newstr = "";
        XmlReader xmlr = XmlReader.Create(new StringReader(str));

        while (xmlr.Read())
        {
            if (xmlr.NodeType == XmlNodeType.Element)
            {
                if (xmlr.Name == "priority")
                {
                    presentvalue = xmlr.ReadElementContentAsString();
                    newstr = str.Replace(presentvalue, newvalue);
                }
            }

        }

//newstrはファイルに書き戻すことができます...つまり編集されたxmlです

于 2010-05-18T16:13:55.977 に答える