XElement の InnerXml を取得する最良の方法は? 質問する

XElement の InnerXml を取得する最良の方法は? 質問する

以下のコード内の混合要素のコンテンツを取得する最適な方法は何ですかbody? 要素には XHTML またはテキストのいずれかが含まれている可能性がありますが、そのコンテンツを文字列形式で取得したいだけです。 type には、まさに私が求めているプロパティがXmlElementあります。InnerXml

書かれたコードほとんど望みどおりの動作をしますが、周囲の<body>...</body>要素が含まれており、これは望ましくありません。

XDocument doc = XDocument.Load(new StreamReader(s));
var templates = from t in doc.Descendants("template")
                where t.Attribute("name").Value == templateName
                select new
                {
                   Subject = t.Element("subject").Value,
                   Body = t.Element("body").ToString()
                };

ベストアンサー1

これらの提案されたソリューションのどれが最も優れているかを確認したかったので、比較テストをいくつか実行しました。興味深いことに、LINQメソッドと従来のメソッドも比較しました。システム.Xmlグレッグが提案した方法。バリエーションは面白く、予想外だった。最も遅い方法は最速より3倍以上遅い

結果は最速から最遅の順に並べられています:

  1. CreateReader - インスタンスハンター (0.113 秒)
  2. 昔ながらの System.Xml - Greg Hurlman (0.134 秒)
  3. 文字列連結による集計 - Mike Powell (0.324 秒)
  4. StringBuilder - Vin (0.333 秒)
  5. 配列の String.Join - Terry (0.360 秒)
  6. 配列上の String.Concat - Marcin Kosieradzki (0.364)

方法

私は 20 個の同一ノード (「ヒント」と呼ばれる) を持つ単一の XML ドキュメントを使用しました。

<hint>
  <strong>Thinking of using a fake address?</strong>
  <br />
  Please don't. If we can't verify your address we might just
  have to reject your application.
</hint>

上記の秒数で示されている数字は、20ノードの「内部XML」を1000回連続で抽出し、5回の実行の平均を取った結果です。XMLをロードして解析するのにかかった時間は含まれていませんXmlDocumentシステム.Xmlメソッド) またはXDocument(その他すべて)。

私が使用した LINQ アルゴリズムは次のとおりです。(C# - すべてXElement「親」を受け取り、内部の XML 文字列を返します)

リーダーを作成:

var reader = parent.CreateReader();
reader.MoveToContent();

return reader.ReadInnerXml();

文字列連結による集計:

return parent.Nodes().Aggregate("", (b, node) => b += node.ToString());

文字列ビルダー:

StringBuilder sb = new StringBuilder();

foreach(var node in parent.Nodes()) {
    sb.Append(node.ToString());
}

return sb.ToString();

配列のString.Join:

return String.Join("", parent.Nodes().Select(x => x.ToString()).ToArray());

配列上の String.Concat:

return String.Concat(parent.Nodes().Select(x => x.ToString()).ToArray());

ここでは、ノード上で .InnerXml を呼び出すだけなので、「単純な古い System.Xml」アルゴリズムは示していません。


結論

パフォーマンスが重要な場合(例えば、大量のXMLを頻繁に解析する場合)、CreateReader毎回ダニエルの方法を使ういくつかのクエリを実行するだけの場合は、Mike のより簡潔な Aggregate メソッドを使用することをお勧めします。

多数のノード (おそらく 100 個) を持つ大きな要素で XML を使用している場合、StringBuilderAggregate メソッドよりも を使用する利点がわかるでしょうが、 よりも優れているとはCreateReader思えません。大きなリストを大きな配列に変換するというペナルティがあるため (ここでは小さなリストでも明らかです)、これらの状況ではJoinおよびConcatメソッドの方が効率的であることはないと思います。

おすすめ記事