2017-01-23 10 views
1

Ich versuche, XML zu analysieren, die ein Element hat, das wie folgt aussieht, die einen XmlSerializer verwenden. Es gibt eine Reihe von Währungstypen unter dem Element "Betrag", und ich möchte sie in eine Sammlung von Objekten deserialisieren, die eine String-Eigenschaft haben, die den Währungstyp enthält, und eine Integer-Eigenschaft, die den Betrag enthält.XmlSerializer Deserialisierung Liste mit verschiedenen Elementnamen

Gibt es einen sauberen Weg, um dies zu tun, ohne die Menge zu analysieren. Ich möchte nur die XmlSerializer-Attribute auf meine Klassen anwenden und etwas erhalten, das funktioniert.

Ich habe keine Kontrolle über die Ausgabe XML.

<root> 
<property1>a</property1> 
<property1>b</property1> 
<property1>c</property1> 
<amount> 
    <EUR type="integer">1000</EUR> 
    <USD type="integer">1100</USD> 
</amount> 
<root> 
+0

Der beste Weg, XML-Deserialisierung angreifen ist es, * serialisierung * zu erhalten, um das gewünschte XML zu generieren. –

Antwort

0

Wie ich in einem Kommentar erwähnt, ist der beste Weg, XML-Deserialisierung zum Angriff zu Beginnen Sie mit Serialisierung. Zu diesem Zweck sind hier einige Klassen mit Attributen zu control XML serialization:

public sealed class root 
{ 
    [XmlElement("property1")] 
    public List<string> property1; 

    [XmlArrayItem(Type = typeof(EUR))] 
    [XmlArrayItem(Type = typeof(USD))] 
    public List<amount> amount; 
} 

public abstract class amount 
{ 
    [XmlAttribute] 
    public string type { get; set; } 

    [XmlText] 
    public string Value { get; set; } 
} 

public sealed class EUR : amount { } 
public sealed class USD : amount { } 

Prüfregeln ist:

 var root = new root { property1 = new List<string>(), amount = new List<amount>() }; 
     root.property1.AddRange(new[]{ "a", "b", "c"}); 
     var eur = new EUR { type = "integer", Value = "1000" }; 
     var usd = new USD { type = "integer", Value = "1100" }; 
     root.amount.AddRange(new amount[]{ eur, usd}); 

, die folgende XML erzeugt:

<?xml version="1.0" encoding="utf-16"?> 
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <property1>a</property1> 
    <property1>b</property1> 
    <property1>c</property1> 
    <amount> 
    <EUR type="integer">1000</EUR> 
    <USD type="integer">1100</USD> 
    </amount> 
</root> 
+0

Ich denke, das ist am nächsten für das, was ich fragte, obwohl ich nicht gerne eine Klasse pro Währungstyp haben. Ich bin mir auch nicht sicher, ob es einen besseren Weg gibt, aber ich habe Reflektion verwendet, um den Währungsnamen mit einer Eigenschaft der abstrakten Klasse zu erhalten, die GetType() zurückgibt. – DSteveson

0

Ich denke, die beste Wahl teilweise XML-Analyse zu tun sein wird, und halten Sie den Inhalt des <amount> Element als eine Sammlung von XmlElement s. Sie müssen es immer noch manuell parsen, aber Sie müssen nur diesen Teil manuell analysieren. Beispiel:

[XmlRoot("root")] 
public class RecordInfo 
{ 
    [XmlElement("property1")] 
    public List<string> Property1; 

    [XmlElement("amount")] 
    public AmountRawData AmountData; 
} 

public class AmountRawData 
{ 
    [XmlAnyElement] 
    public List<XmlElement> Content; 

    public IEnumerable<AmountInfo> Parse() 
    { 
     foreach (var element in this.Content) 
     { 
      yield return 
       new AmountInfo() 
       { 
        Currency = element.LocalName, 
        Type = element.GetAttribute("type"), 
        Amount = element.InnerText, 
       }; 
     } 
    } 
} 

public class AmountInfo 
{ 
    public string Currency; 
    public string Type; 
    public string Amount; 
} 

Beispiel Nutzung:

var serializer = new XmlSerializer(typeof(RecordInfo)); 

var result = (RecordInfo)serializer.Deserialize(dataStream); 

foreach (var amount in result.AmountData.Parse()) 
    Console.WriteLine($"{amount.Currency} {amount.Type} {amount.Amount}"); 
-1

Beantwortet ähnliche Frage letzte Woche xml linq mit

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Xml; 
using System.Xml.Linq; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     const string FILENAME = @"c:\temp\test.xml"; 
     static void Main(string[] args) 
     { 
      XDocument doc = XDocument.Load(FILENAME); 

      var results = doc.Elements().Select(x => new { 
       property1 = x.Elements("property1").Select(y => (string)y).ToList(), 
       dictCurrency = x.Elements("amount").Elements().GroupBy(y => y.Name.LocalName, z => (int)z) 
        .ToDictionary(y => y.Key, z => z.FirstOrDefault()) 
      }).FirstOrDefault(); 

     } 
    } 
} 
Verwandte Themen