在反序列化之前如何区分XML文件的类型?

时间:2014-05-14 19:19:08

标签: c# xml deserialization xmlserializer musicxml

我正在将MusicXML文件加载到我的程序中。问题:有两种“方言”, timewise partwise ,它们有不同的根节点(和不同的结构):

<?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>

<?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>

到目前为止,用于反序列化分段分数的代码是:

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

区分两种方言的最佳方法是什么?

3 个答案:

答案 0 :(得分:5)

这是通过使用XDocument来解析文件,读取根元素以确定类型并将其读入序列化程序来实现此目的的方法。

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 :(得分:2)

我会创建两个序列化程序

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

假设只有这两个我会在一个

上调用 CanDeserialize 方法
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);
    }
  }
}

显然,这只是一个想法,如何做到这一点。如果有更多选项或根据您的应用程序设计,我会使用更复杂的方式来调用 CanDeserialize ,但该方法是我认为的关键:

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

可以在此处找到XmlReader类:

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

答案 2 :(得分:0)

如果您担心资源使用情况:

    internal const string NodeStart = "<Error ";
    public static bool IsErrorDocument(string xml)
    {
        int headerLen = 1;
        if (xml.StartsWith(Constants.XMLHEADER_UTF8))
        {
            headerLen += Constants.XMLHEADER_UTF8.Length;
        }
        else if (xml.StartsWith(Constants.XMLHEADER_UTF16))
        {
            headerLen += Constants.XMLHEADER_UTF16.Length;
        }
        else
        {
            return false;
        }
        if (xml.Length < headerLen + NodeStart.Length)
        {
            return false;
        }
        return xml.Substring(headerLen, NodeStart.Length) == NodeStart;
    }

internal class Constants
{
    public const string XMLHEADER_UTF16 = "<?xml version=\"1.0\" encoding=\"utf-16\"?>";
    public const string XMLHEADER_UTF8 = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
}