【问题标题】:'System.InvalidOperationException' occurred in System.Xml.dllSystem.Xml.dll 中发生“System.InvalidOperationException”
【发布时间】:2015-04-14 12:09:43
【问题描述】:

我尝试解析以下网站的 XML:PubMed

我正在使用以下代码来完成这项工作:

public void SearchByURI(string keyword)
{
    string URI = "http://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=pubmed&term=" + keyword;
    System.Xml.Serialization.XmlSerializer reader = new System.Xml.Serialization.XmlSerializer(typeof(eSearchResult));
    XmlReader xmlReader = XmlReader.Create(URI);
    eSearchResult result = new eSearchResult();
    result = (eSearchResult)reader.Deserialize(xmlReader);
}

但是当我运行代码时,它在最后一行崩溃,并出现以下异常:

System.Xml.dll 中出现“System.InvalidOperationException”类型的异常,但未在用户代码中处理。附加信息:XML 文档中存在错误 (0, 0)。

XML应该被序列化到的类可以在下面的pastbin中找到,这里粘贴有点大。 PasteBin link.此代码由Visual Studio生成

【问题讨论】:

  • XML 序列化器是一个相当猛兽,让它与 DTD 互操作确实非常复杂。尽管这不是您问题的直接答案,但您可能需要考虑将数据加载到 XElement 中,然后自己将其拆开。虽然代码更多,但也更容易排除故障。
  • 好的!非常感谢,我会试试这个!

标签: c# xml visual-studio


【解决方案1】:

所以我为解决以下问题所做的就是使用 XElement 作为 Jeroen Mostert 的建议。

首先,我按照以下post 中的建议创建了扩展方法,如下所示:

public static XElement ToXElement<T>(this object obj)
    {
        using (var memoryStream = new MemoryStream())
        {
            using (TextWriter streamWriter = new StreamWriter(memoryStream))
            {
                var xmlSerializer = new XmlSerializer(typeof(T));
                xmlSerializer.Serialize(streamWriter, obj);
                return XElement.Parse(Encoding.ASCII.GetString(memoryStream.ToArray()));
            }
        }
    }

    public static T FromXElement<T>(this XElement xElement)
    {
        using (var memoryStream = new MemoryStream(Encoding.ASCII.GetBytes(xElement.ToString())))
        {
            var xmlSerializer = new XmlSerializer(typeof(T));
            return (T)xmlSerializer.Deserialize(memoryStream);
        }
    }

然后我将上面的代码更改为以下代码:

 public eSearchResult SearchByURI(string keyword)
    {
        string URI = "http://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=pubmed&term=" + keyword;
        XElement xml = XElement.Load(URI);
        eSearchResult pubMedResult = xml.FromXElement<eSearchResult>();
        return pubMedResult; 
    }

【讨论】:

  • 那...不是我的想法,我正在考虑编写代码以手动将XElement 转换为eSearchResult。这里发生的情况是,我们首先使用XElement 解析XML,然后再次将其变为字符串,然后使用XmlSerializer 再次解析它!但如果这可行,那么这意味着直接使用 XmlSerializer 解析它也应该可以正常工作,并且还有一些其他微妙的问题会导致序列化程序在直接从 URI 读取时失败。这需要进一步调查。
  • 不管解决方案的适当性如何,使用Encoding.ASCII 进行序列化都是一个坏主意,因为它没有涵盖Unicode 的全部范围。 Encoding.UTF8 是一个更好的主意。
  • 好的,再次感谢,我误会你了。我稍后会尝试你的方法。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多