1. ホーム
  2. .net

[解決済み] XElementのInnerXmlを取得する最良の方法は?

2022-05-01 07:24:16

質問

の内容を取得するのに最適な方法は何ですか? body 要素を使用することができますか? この要素にはXHTMLかテキストが含まれているかもしれませんが、私はその内容を文字列で知りたいだけです。 その 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()
                };

解決方法は?

そこで、これらの提案された解決策のうち、どれが一番うまく機能するかを確認するために、いくつかの比較テストを行いました。興味本位で、LINQメソッドと昔ながらの System.Xml メソッドを提案しました。そのバリエーションは興味深く、私が予想していたものとは違っていました。最も遅いメソッドは の3倍以上遅い。 .

結果が早い順に並んでいます。

  1. CreateReader - Instance Hunter(0.113秒)
  2. 平凡なSystem.Xml - Greg Hurlman (0.134秒)
  3. 文字列連結による集計 - Mike Powell (0.324秒)
  4. StringBuilder - Vin (0.333秒)
  5. String.Join on array - Terry (0.360秒)
  6. String.Concat on array - Marcin Kosieradzki (0.364)

方法

20個の同一ノードを持つ1つのXML文書('hint'と呼ぶ)を使用しました。

<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ノードの"inner XML"を1000回連続で抽出し、5回実行したときの平均(mean)を取った結果です。XMLをロードしてパースして XmlDocument (の場合)。 システム.Xml メソッド)または XDocument (それ以外の場合)です。

使用したLINQのアルゴリズムは (C# - すべて XElement 親となるXML文字列を返します)

CreateReaderを使用します。

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

return reader.ReadInnerXml();

文字列連結で集計する。

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

StringBuilderです。

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 を呼び出すだけなので、ここでは "Plain old System.Xml" アルゴリズムを表示していません。


結論

パフォーマンスが重要な場合(例:大量のXML、頻繁にパースされる)、私は次のようにします。 は、ダニエルの CreateReader メソッドを毎回 . もし、いくつかのクエリを実行するだけなら、Mikeのもっと簡潔なAggregateメソッドを使用したほうがいいかもしれません。

もしあなたが、たくさんのノード(100個くらい)を持つ大きな要素でXMLを使っているのなら、おそらく StringBuilder は、Aggregateメソッドより優れていますが CreateReader . 私は JoinConcat というのは、大きなリストを大きな配列に変換すると、ペナルティが発生するからです(小さなリストであればなおさらです)。