名前空間を使用して、XMLに格納されているオブジェクトの逆シリアル化を支援するアプリケーションがあります。XML名前空間は、オブジェクトが存在するC#名前空間でもあります。たとえば、次のXMLスニップがあるとします。
<xml-config xmlns:app="MyAppNS">
<app:Person>
<Name>Bill</Name>
<Car>
<Make>Honda</Make>
<Model>Accord</Model>
</Car>
</app:Person>
<app:Person>
<Name>Jane</Name>
<Car>
<Make>VW</Make>
<Model>Jetta</Model>
</Car>
</app:Person>
<app:Car>
<Make>Audi</Make>
<Model>A6</Model>
</app:Car>
</xml-config>
構成は、実際には単なるオブジェクトのランダムなバッグです。ご覧のとおり、トップレベルにはPerson
とオブジェクトが混在しています。Car
名前空間を使用して、適切な逆シリアル化のためにロード時にオブジェクトタイプを決定します。ドキュメントをロードするためのコードは次のとおりです。
public static void LoadFile(String file) {
XmlDocument doc = new XmlDocument();
doc.Load(file);
XmlNode root = doc.DocumentElement;
foreach (XmlNode child in root.ChildNodes) {
if (child.NodeType != XmlNodeType.Element) {
continue;
}
Object obj = LoadObject(child);
// TODO handle object here...
}
}
private static Object LoadObject(XmlNode node) {
Object obj = null;
StringBuilder str = new StringBuilder();
if ((node.Prefix != null) && (node.Prefix != "")) {
str.Append(node.NamespaceURI).Append('.');
}
str.Append(node.LocalName);
Assembly assy = Assembly.GetExecutingAssembly();
Type type = assy.GetType(str.ToString());
XmlSerializer serdes = new XmlSerializer(type);
using (XmlNodeReader reader = new XmlNodeReader(node)) {
obj = serdes.Deserialize(reader);
}
return obj;
}
多くの人がすぐに問題を認識しますが、このコードを使用すると、結果のPerson
オブジェクトは空になりますが、エラーは発生しません。デシリアライザーに子要素を設定する唯一の方法は、子要素に同じ名前空間を使用することです。
<app:Person>
<app:Name>Bill</app:Name>
<app:Car>
<app:Make>Honda</app:Make>
<app:Model>Accord</app:Model>
</app:Car>
</app:Person>
私が試した他の唯一のオプションは、要素名として完全修飾型名を使用することです(名前空間なし)が、それはうまくいきませんでした。デシリアライザーにXMLノードのプレフィックスなしの子を受け入れさせる方法はありますか?