未定義の名前空間プレフィックスを使用したXMLの逆シリアル化
-
05-07-2019 - |
質問
私が受け取るXml応答は次のとおりです。
<response>
<item xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="java:com.someDomain.item">
<name>some name</disc-name>
<description>some description</disc-desc>
</item>
<item xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="java:com.someDomain.item">
<name>some name</disc-name>
<description>some description</disc-desc>
</item>
<otherValue>12.1</otherValue>
</response>
私のクラスはそのように装飾されています:
[XmlElement("item")]
public Item[] Items{get;set;}
[XmlElement("otherValue")
public string OtherValue{get;set;}
上記のXmlを説明したクラスにデシリアライズしようとすると、<!> quot; Namespace prefix 'java' is notdefined <!> quot;というエラーが表示されます。 <!> quot; namespace <!> quot;の追加クラスの属性により解析エラーが解決されます(ただし、xmlは元のものから歪められます)。
ie
[XmlElement(ElementName="item",Namespace="java")]
新しい名前空間と一致するように、特定のプロパティをどのように装飾する必要がありますか?または、どのように名前空間を正しく定義しますか?
列挙可能なセクションにストック配列を使用することも100%ではありませんが、現時点では名前空間の問題が優先されると思います。洞察や考えは大歓迎です!
更新:
質問をやり直したほうがいいと思います:
XmlElementAttribute(または他の属性)を使用して、xsiタグを含む上記のアイテムスニペットにシリアル化できるクラスを作成するにはどうすればよいですか?
私の特定の問題に関しては、Xml応答が制御できないため、最初にxsi属性は必要ないことに気付きました。シリアル化の問題を回避するには、次のことを行うだけです(XmlElement要素には上記の元のドキュメントが含まれています):
foreach(XmlNode node in element)
node.Attributes.RemoveAll();
これは実際には解決策ではないため、個人的な回避策にのみ注目しています。
解決
残念ながら、これは有効なXMLであり、XML標準に完全に準拠しています。 検証、正確、完全です。
問題はデシリアライゼーションにあります。これはXML標準の一部ではなく、.NETが宣言されたXML型を内部CLR型にマップする方法に関連しています。
xsi:typeは名前空間の参照であり、XMLドキュメントがスキーマ内の宣言された型を別の名前空間から派生した型に置き換えることを可能にすることを目的としています。
私自身の経験から、コーダーはショックで反応する傾向があることを知っています。この種のものは合法であり、はるかに正確ではないXMLです。基本的にスキーマをハイジャックします。
これが正しいと見なされるために、外部の名前空間を含める必要さえありません。
(この件に関するさらなる暴言については、この記事を参照してください: http:// norman。 walsh.name/2004/01/29/trainwreck )
今、あなたの述べられた問題をどのように扱うかに関して:この混乱をデシリアライズしてください。 1)xmlテキストを処理し、xsi-types宣言を削除し、基本型を拡張するフィールドが宣言されていないことを期待します。 2)スキーマの基本型から派生した型を宣言します。
これは次のようになります。
// note this "XmlIncludeAttribute" references the derived type.
// note that in .NET they are in the same namespace, but in XML they are in different namespaces.
[System.Xml.Serialization.XmlIncludeAttribute(typeof(DerivedType))]
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://BaseNameSpace")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://BaseNameSpace", IsNullable=true)]
public partial class MyBaseType : object
{
...
}
/// <remarks/>
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://DerivedNameSpace")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://DerivedNameSpace", IsNullable=true)]
public partial class DerivedType: MyBaseType
{
...
}
これは大まかな概要にすぎませんが、開始するのに十分です。これは、誰かがXMLをフィードすることは常に可能であり、検証はされますが、適切にデシリアライズされないため、プログラムで解決するのは簡単な問題ではないことに注意してください。
他のヒント
初めて正しかった。 <!> quot; java <!> quot;名前空間ではありません。名前空間プレフィックスです。これは、XMLで使用するための名前空間の略語です。そうしないと、実際に<!> quot; java:<!> quot;が表示されている場所であればどこでも、実際のネームスペースを繰り返す必要があります。
List<Item>
の代わりにItem[]
を使用できます。