次の方法で共有


インメモリ XML ツリーの変更と関数型構築 (LINQ to XML)

XML ツリーをインプレースで変更することは、XML ドキュメントの形状を変更するための従来のアプローチです。 一般的なアプリケーションでは、DOM や LINQ to XML などのデータ ストアにドキュメントを読み込みます。は、プログラミング インターフェイスを使用してノードを挿入または削除したり、その内容を変更したりします。XML をファイルに保存するか、ネットワーク経由で送信します。

LINQ to XML を使用すると、多くのシナリオで役立つもう 1 つのアプローチ ( 関数型構築) が可能になります。 機能構築では、データの変更は、データ ストアの詳細な操作としてではなく、変換の問題として扱われます。 データを表現し、あるフォームから別のフォームに効率的に変換できる場合、結果は、あるデータ ストアを取得して別の図形を作成するために何らかの方法で操作した場合と同じです。 関数型構築アプローチの鍵となるのは、クエリの結果を XDocument コンストラクターと XElement コンストラクターに渡すことです。

多くの場合、変換コードはデータ ストアの操作にかかる時間のごく一部で記述でき、結果のコードはより堅牢で保守が容易になります。 このような場合、変換アプローチは処理能力を高めることができますが、データを変更するより効果的な方法です。 開発者が関数型アプローチに慣れている場合、多くの場合、結果のコードは理解しやすくなり、ツリーの各部分を変更するコードを簡単に見つけることができます。

XML ツリーを適切に変更する方法は、多くの DOM プログラマにとってより使い慣れているのに対し、関数型アプローチを使用して記述されたコードは、そのアプローチをまだ理解していない開発者には馴染みがない場合があります。 大きな XML ツリーに対して小さな変更のみを行う必要がある場合、多くの場合、ツリーを変更する方法では CPU 時間が短くなります。

この記事では、両方の方法の例を示します。 属性が要素になるように、次の単純な XML ドキュメントを変更するとします。

<?xml version="1.0" encoding="utf-8" ?>
<Root Data1="123" Data2="456">
  <Child1>Content</Child1>
</Root>

次の例の最初の例では、従来のインプレース変更アプローチを使用し、2 番目の例では機能構築アプローチを使用します。

例: 従来のインプレース アプローチを使用して属性を要素に変換する

属性から要素を作成し、次のように属性を削除する手順コードを記述できます。

XElement root = XElement.Load("Data.xml");
foreach (XAttribute att in root.Attributes()) {
    root.Add(new XElement(att.Name, (string)att));
}
root.Attributes().Remove();
Console.WriteLine(root);
Dim root As XElement = XElement.Load("Data.xml")
For Each att As XAttribute In root.Attributes()
    root.Add(New XElement(att.Name, att.Value))
Next
root.Attributes().Remove()
Console.WriteLine(root)

この例では、次の出力が生成されます。

<Root>
  <Child1>Content</Child1>
  <Data1>123</Data1>
  <Data2>456</Data2>
</Root>

例: 関数型構築アプローチを使用して属性を要素に変換する

これに対し、機能的アプローチは、新しいツリーを形成するコード、ソース ツリーから要素と属性を選択して選択し、新しいツリーに追加された場合に適宜変換するコードで構成されます。

XElement root = XElement.Load("Data.xml");
XElement newTree = new XElement("Root",
    root.Element("Child1"),
    from att in root.Attributes()
    select new XElement(att.Name, (string)att)
);
Console.WriteLine(newTree);
Dim root As XElement = XElement.Load("Data.xml")
Dim newTree As XElement = _
    <Root>
        <%= root.<Child1> %>
        <%= From att In root.Attributes() _
            Select New XElement(att.Name, att.Value) %>
    </Root>
Console.WriteLine(newTree)

この例では、最初の例と同じ XML を出力します。 ただし、関数型アプローチでは、新しい XML の結果の構造を実際に確認できることに注意してください。 Root要素の作成、ソース ツリーからChild1要素をプルするコード、およびソース ツリーから新しいツリー内の要素に属性を変換するコードを確認できます。

この場合の機能例は、最初の例よりも短くも単純でもありません。 ただし、XML ツリーに対して多くの変更を加えた場合、手続き型のアプローチは非常に複雑になり、やや難しくなります。 これに対し、関数型アプローチを使用する場合でも、必要な XML を作成するだけで、必要なコンテンツを取り込むクエリと式が必要に応じて埋め込まれます。 関数型アプローチでは、保守が容易なコードが生成されます。

この場合、機能アプローチはツリー操作アプローチと同様に実行されない可能性があることに注意してください。 主な問題は、関数型アプローチにより、有効期間の短いオブジェクトが作成されるということです。 ただし、関数型アプローチを使用してプログラマの生産性を向上できる場合は、トレードオフが効果的です。

これは非常に単純な例ですが、2 つのアプローチの哲学の違いを示すために役立ちます。 関数型アプローチを使用すると、大きな XML ドキュメントを変換する際の生産性が向上します。