2014-05-14 2 views
6

Ich lade MusicXML-Dateien in mein Programm. Das Problem: Es gibt zwei „Dialekte“, zeitlich und halb abgetrennte, den unterschiedlichen Wurzelknoten (und eine andere Struktur) haben:Wie differenziere ich XML-Dateitypen vor der Deserialisierung?

<?xml version="1.0" encoding='UTF-8' standalone='no' ?> 
<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 2.0 Partwise//EN" "http://www.musicxml.org/dtds/partwise.dtd"> 
<score-partwise version="2.0"> 
    <work>...</work> 
    ... 
</score-partwise> 

und

<?xml version="1.0" encoding="UTF-8" standalone="no"?> 
<!DOCTYPE score-timewise PUBLIC "-//Recordare//DTD MusicXML 2.0 Timewise//EN" "http://www.musicxml.org/dtds/timewise.dtd"> 
<score-timewise version="2.0"> 
    <work>...</work> 
    ... 
</score-timewise> 

Mein Code für Deserialisieren die halb abgetrennte Partitur so weit ist:

using (var fileStream = new FileStream(openFileDialog.FileName, FileMode.Open)) 
{ 
    var xmlSerializer = new XmlSerializer(typeof(ScorePartwise)); 
    var result = (ScorePartwise)xmlSerializer.Deserialize(fileStream); 
} 

Was wäre der beste Weg, um zwischen den beiden Dialekten zu unterscheiden?

+0

Wie groß sind die XML-Dateien? – EkoostikMartin

+0

Das hängt wirklich vom Stück ab, eine durchschnittliche Motette von Palestrina mit vier Stimmen hat etwa 12000 Zeilen/300 KB. Eine ganze Symphonie wird definitiv mehr haben. –

+1

Okay, ich würde die dritte Zeile der Datei in einen String laden und dann '' String.IndexOf() ''entweder nach Teil oder Zeit suchen, dann weiß man, mit welchem ​​Dateityp man es zu tun hat und kann wählen richtiger Serializer. – EkoostikMartin

Antwort

5

Hier ist ein Weg, es zu tun, indem sie ein XDocument mit der Datei, lesen sie das root-Element zu analysieren, um die Art zu bestimmen und es in Ihren Serializer zu lesen.

var xdoc = XDocument.Load(filePath); 
Type type; 
if (xdoc.Root.Name.LocalName == "score-partwise") 
    type = typeof(ScorePartwise); 
else if (xdoc.Root.Name.LocalName == "score-timewise") 
    type = typeof(ScoreTimewise); 
else 
    throw new Exception(); 
var xmlSerializer = new XmlSerializer(type); 
var result = xmlSerializer.Deserialize(xdoc.CreateReader()); 
+1

Das Laden des gesamten XML-Dokuments, nur um die erste Zeile zu prüfen, wird etwas langsam sein, wenn man bedenkt, dass die Datei mindestens 12000 Zeilen hat. – EkoostikMartin

+0

Sie sind dabei, die ganze Datei zu lesen, indem Sie sie sowieso deserialisieren. Es lesen -> erste Zeile prüfen -> In-Memory-Datei an Deserializer senden kann nicht schlecht sein (unter der Annahme, Speicherverbrauch ist nicht so schlecht; ich nehme an, die Datei ist in der Zehner von MB oder weniger, was sein sollte fein). –

2

ich beide Serializer schaffen würde

var partwiseSerializer = new XmlSerializer(typeof(ScorePartwise)); 
var timewiseSerializer = new XmlSerializer(typeof(ScoreTimewise)); 

Unter der Annahme, dass es nur diese beiden ich CanDeserialize Methode auf einer

using (var fileStream = new FileStream(openFileDialog.FileName, FileMode.Open)) 
{ 
    using (var xmlReader = XmlReader.Create(filStream)) 
    { 
    if (partwiseSerializer.CanDeserialize(xmlReader)) 
    { 
     var result = partwiseSerializer.Deserialize(xmlReader); 
    } 
    else 
    { 
     var result = timewiseSerializer.Deserialize(xmlReader); 
    } 
    } 
} 

nennen würde Natürlich ist dies nur eine Idee, wie es geht. Wenn es mehr Optionen waren oder nach der Anwendung Design würde ich eine anspruchsvollere Art und Weise verwendet CanDeserialize zu nennen, aber das Verfahren ist der Schlüssel meiner Meinung nach:

http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer.candeserialize.aspx

Die XmlReader-Klasse finden Sie hier :

http://msdn.microsoft.com/en-us/library/System.Xml.XmlReader(v=vs.110).aspx

Verwandte Themen