まず、私は .NET 2.0 に制約されているため、LINQ は私にとって選択肢ではありません (ただし、LINQ ソリューションがプロジェクトの .NET 3.5 への移行を推進するための餌食となるのが簡単な場合)。
ビルド時に xsd.exe を介して一連の C# クラスに変換される XSD があります。実行時に、XML ファイルがロードされ、C# クラスに逆シリアル化されます (この時点で検証が行われます)。次に、メモリ内の構成オブジェクト (XML ファイルのインポート中に入力された既定値を含む) を、キーと値のペアのディクショナリに変換する必要があります。
辞書のキーを値へのドット区切りのパスにしたいと思います。属性値と要素テキストは値と見なされ、他のすべてはそのキーになります。
例として、次の XML ファイルを想像してください。
<rootNode>
<foo enabled="true"/>
<bar enabled="false" myAttribute="5.6">
<baz>Some Text</baz>
<baz>Some other text.</baz>
</bar>
</rootNode>
次のようなキーを持つ辞書になります。
"rootNode.foo.enabled" = (Boolean)true
"rootNode.bar.enabled" = (Boolean)false
"rootNode.bar.myAttribute" = (Float)5.6
"rootNode.bar.baz" = List<String> { "Some Text", "Some other text." }
注意すべきことは、rootNode が省略されているのは、それが特別だからではなく、テキストや属性がないためです。また、ディクショナリは、適切に型付けされたオブジェクトのディクショナリです (これは、デシリアライズで既に行われています。これが、XML を直接ではなく C# オブジェクトで作業したい理由の 1 つです)。
興味深いことに、xsd.exe によって作成されたオブジェクトは、既に私が求めている形に非常に近いものになっています。クラス名は、myAttribute と呼ばれる float フィールドを持つ rootNodeFoo のようなものです。
私が検討したことの 1 つは、リフレクションを使用してオブジェクト ツリーを反復処理し、各オブジェクトのクラスの名前を使用してノードの名前を特定することです (ケーシングを微調整する必要がある場合があります)。少し)。これに関する問題は、それが間違った解決策のように感じられることです。これは、すべてのことをより高速に行うことができるはずのデシリアライザーに既にアクセスできるためです。
もう 1 つのオプションは、XSLT を使用して、データを希望の形式に直接シリアル化することです。ここでの問題は、私の XSLT の知識が限られていることです (間違っている場合は訂正してください) 途中で入力を失うと思います (すべてが文字列になります)。バックアウトします (今回は、.NET デシリアライザーを使用したときに得られる XSD 検証なし)。
重要な場合に備えて、XML ファイルから設定オブジェクトを取得するために使用している呼び出しは、次のようなものです。
var rootNode = new XmlRootAttribute();
rootNode.ElementName = "rootNode";
rootNode.Namespace = "urn:myNamespace";
var serializer = new XmlSerializer(typeof(rootNode), rootNode);
using (var reader = new StringReader(xmlString))
{
var deserializedObject = (rootNode)serializer.Deserialize(reader);
}