2017-06-30 3 views
0

今日、私はサードパーティのバックエンドから更新されたXMLコンテンツを入手し、新しいフィールドに準拠するためにXmlSerializerベースの解析コードを変更する必要がありました。残念ながら、私はそこに似たタグのコレクションを紹介しましたが、奇妙な行動をしていることを考え出し:C#XmlSerializerとさまざまなタグ名のコレクション[UWP]

<old-root> 
    ... 
    <contacts> 
    <John>Feel happy</John> 
    <Mary>Will be away for 2 hours, phone me</Mary> 
    <Bob>Do not disturb. I mean it!</Bob> 
    ...and so on... 
    </contacts> 
</root> 

これまでは、[のXmlElement]マッピングに基づいて、「古いルート」のためのパーサクラスを持っていたが、私はしませんでしたXMLアノテーション([XmlArray]/[XmlArrayItem]などのようなもの)が、同様の名前と値のペアのコレクションを管理する方法をまだ理解していません。 [XmlText]アノテーションを使って値を取得できますが、そのanyタグに注釈を付ける方法はありますか? 「星」パターンはElementNameには影響しません。

P.S.私は.NETフレームワークのUWPサブセットを使っています。

+0

設計時にノード,が知られていますか?あるいは、彼らは任意のノードですか? – JuanR

+0

@Juan、正確な名前は設計時にはわかりません。あなたがバックエンドから受け取ったコンタクトリストのようなものです。 –

+0

属性を使用するあなたの戦略はもはや十分ではありません。あなたは基本的なシリアライゼーションを超えているので、カスタムのシリアライザ/デシリアライザを実装する必要があります。 – JuanR

答えて

1

私は次のアプローチを提案できます。異なるタグには辞書を使用してください。 XmlSerializerは辞書では使用できないため、XmlIgnore属性でマークし、データを手動で逆シリアル化します。

[XmlRoot("old-root")] 
public class Root 
{ 
    [XmlIgnore] 
    public Dictionary<string, string> Contacts { get; set; } 
} 

まずXElementにXMLを読み込み、ノードcontactsから辞書を作成します。そのノードを削除します。次に、XElementからデータを逆シリアル化します。最後に、前に作成した辞書を設定します。

var xs = new XmlSerializer(typeof(Root)); 
Root root = null; 
StorageFolder folder = ApplicationData.Current.LocalFolder; 

using (var stream = await folder.OpenStreamForReadAsync("test.xml")) 
{ 
    var xml = XElement.Load(stream); 
    var contacts = xml.Element("contacts"); 
    var dict = contacts.Elements().ToDictionary(x => x.Name.LocalName, x => x.Value); 
    contacts.Remove(); 

    root = (Root)xs.Deserialize(xml.CreateReader()); 
    root.Contacts = dict; 
} 

メモリ消費の観点とパフォーマンスの観点からはどちらも非効率的であるため、かなり醜いです。しかしそれは簡単で簡単です。

+0

スタンドアロン.NETには最適です。残念ながら、私はUWPサブセットを使っています。その情報で質問を更新します。 –

+0

@ YurySchkatula - 更新を参照してください。 –

+0

ラッパークラスのIXmlSerializableの助けを借りて非常によく似たコードでした。私はまだよりエレガントな方法があることを願っています... –

関連する問題