2009-10-01 24 views
6

XmlReaderが渡されるメソッドをオーバーライドしています。特定の要素を見つけて属性を追加し、新しいXmlReaderを作成するか、変更されたコンテンツを持つ既存のもの私はC#4.0を使用していますXmlReader - 要素を編集して新しい要素を作成する必要があります。

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

答えて

11

たXmlReader /ライター可能性も観察されてきました順次アクセスストリームです。あなたは一端を読み込み、ストリームを処理し、もう片方を書き出す必要があります。利点は、全体をメモリに読み込んで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を導出するほどきれいではありませんが、私はそれがはるかに簡単だということを見つけます。

[EDIT]

あなたはこのようなものかもしれません一度に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); 
    } 
} 
1

あなたは簡単にXmlReaderでこれを行うことはできません - 少なくとも、ない読者からでXML文書全体を読むことなく、それをfutzingし、その結果から新しいXmlReaderを作成します。それは、しかし、XmlReaderを使用してポイントの多くを破る - すなわち、大きなドキュメントをストリーミングする能力。

あなたは潜在XmlReaderから派生することができ、転送ほとんどの方法は、既存のリーダーに呼び出しますが、どこの余分な属性などを添加することが適切とそれらをインターセプト...しかし、私は、コードは実際にはかなり複雑で壊れやすいだろうと思われます。

+0

返信ありがとう、私は(希望)これは素敵な簡単な操作になると思った。これまでにXMLを特定の要素まで読み込み、編集してから変更された結果を出力したいと思った唯一の人になることはできません。 - 今日レディングでいつもより誓いを聞いたら....それは私です! –

+0

@Phill:それはXmlReader'は(あなたが抽象メソッドの多くを実装するように感じない限り、実際には、 'XmlTextReader'をサブクラス化したい)である'サブクラス:(ちょうどストリーミング方式で、私は怖いではない、それを行うのは簡単だ –

+0

興味深い課題 –

1

私は、私はむしろXmlDocumentにXMLをロードすることを好むだろう....私はこのようにそれをやって、それが働いているために汚い感じ

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

をコーディング、次のダクトテープを使用して

+1

は、私はそれが働いていることを確認してくださいそうではないでしょうあなたが返す読者はするつもりはありませんその要素(元のリーダーが処理していた残りのXML文書のすべて)がそのバッキングストリームにないため、この要素の後の要素に移動することができます。 –

0

それを固定値を変更するには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を使用するときに空白が正しく保存されていなかった、これは厄介な、時には

-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です

関連する問題