XDocument解析错误

时间:2018-02-14 02:30:57

标签: c# linq-to-xml xmlreader

我已经通过API访问数据库多年了,今天我做了一些更改,但我无法联系所有者。它似乎是一个微妙的变化导致我的代码给出Null引用异常。 下载文件,然后我尝试使用XmlReader并使用以下代码将其加载到字典中:

Dictionary<decimal, string> dict = new Dictionary<decimal, string>();

using (var file = File.Open(dir + @"\dxcc_matrix.gz", FileMode.Open))
{
    using (var zip = new GZipStream(file, CompressionMode.Decompress))
    {
        using (var xmlReader = XmlReader.Create(zip))
        {
            var xd = XDocument.Load(xmlReader); 

            dict =    //error occurs here
            xd
                .Document
                .Root
                .Element(XName.Get("entities", "http://www.clublog.org/cty/v1.0"))
                .Elements(XName.Get("entity", "http://www.clublog.org/cty/v1.0"))
                .ToDictionary(
                    x => (decimal)x.Element(XName.Get("adif", "http://www.clublog.org/cty/v1.0")),
                    x => x.Element(XName.Get("name", "http://www.clublog.org/cty/v1.0")).Value);
        }
    }
}

部分XML文件如下所示:

<clublog date="2018-02-13T21:30:11+00:00" 
        xmlns="https://clublog.org/cty/v1.0">
<entities>
<entity>
    <adif>1</adif>
    <name>CANADA</name>
    <prefix>VE</prefix>
    <deleted>FALSE</deleted>
    <cqz>5</cqz>
    <cont>NA</cont>
    <long>-80.00</long>
    <lat>45.00</lat>
</entity>
<entity>
    <adif>2</adif>
    <name>ABU AIL IS</name>
    <prefix>A1</prefix>
    <deleted>TRUE</deleted>
    <cqz>21</cqz>
    <cont>AS</cont>
    <long>45.00</long>
    <lat>12.80</lat>
    <end>1991-03-30T23:59:59+00:00</end>
</entity>
<!--Additional entities omitted-->
</entities>
</clublog>

我的代码中是否突然出现问题,或者当前代码的XML无法使用?

2 个答案:

答案 0 :(得分:1)

这可能是由搜索XML中实际不存在的元素引起的。
在这种情况下,将抛出Null引用异常。如果更改是在XML本身进行的,则可能是错误原因。

答案 1 :(得分:1)

您的问题是,在某些版本的XML中,<entity><entities>元素位于"http://www.clublog.org/cty/v1.0" XML命名空间中,但在其他版本中,它们位于{{1}命名空间。

为了解析XML版本,您需要检查两个可能的命名空间中的元素,例如使用以下方法:

"https://clublog.org/cty/v1.0"

注意:

  • 您可能会将XML命名空间public static class AdifDictionaryExtensions { public static Dictionary<decimal, string> ExtractAdifDictionary(TextReader reader) { Dictionary<decimal, string> dict = new Dictionary<decimal, string>(); using (var xmlReader = XmlReader.Create(reader)) { var xd = XDocument.Load(xmlReader); var ns1 = (XNamespace)"http://www.clublog.org/cty/v1.0"; var ns2 = (XNamespace)"https://clublog.org/cty/v1.0"; dict = xd .Root .Elements("entities", ns1, ns2).Single() .Elements("entity", ns1, ns2) .ToDictionary( x => (decimal)x.Elements("adif", ns1, ns2).Single(), x => x.Elements("name", ns1, ns2).Single().Value); return dict; } } } public static class XContainerExtensions { public static IEnumerable<XElement> Elements(this XContainer container, string localName, XNamespace nameSpace, params XNamespace[] additionalNamespaces) { if (container == null || localName == null) throw new ArgumentNullException(); var names = new[] { nameSpace }.Concat(additionalNamespaces).Select(ns => ns + localName).ToArray(); return container.Elements().Where(e => names.Any(n => n == e.Name)); } } "http://www.clublog.org/cty/v1.0"视为可能会或可能不会解析为同一地址的实际URL。但是,从XML解析的角度来看,这些命名空间只是字符串,有助于在组合成大型异构XML文档时提供元素和属性的唯一命名。 (有关详细说明,请参阅 XML namespace 。)

    使用XContainer.Element(XName)XContainer.Elements(XName)按名称在LINQ to XML层次结构中搜索元素时,重要的是local namenamespace是否具有所需的本地名称和命名空间使用序数字符串比较。

  • 尽管名称如此,XName.Get()实际上并不执行http get或任何其他网络操作。它是一种工厂方法,它将两个字符串组合成XName类,以进行性能相等比较。

示例工作.Net fiddle