【问题标题】:parse xml and load in dictionary解析 xml 并加载到字典中
【发布时间】:2014-03-17 11:25:38
【问题描述】:

我想解析一个使用以下模式的 XML 文件,并提取两个元素“adif”和“name”中的数据并将它们放入字典中。 我真的不知道如何使用任何内置的 .net 类或 HTML Agility Pack 来解决这个问题。

有人可以向我发送正确的方向吗? 谢谢

<?xml version="1.0" encoding="utf-16"?>
 <xs:schema xmlns="http://www.clublog.org/cty/v1.0" attributeFormDefault="unqualified"         elementFormDefault="qualified" targetNamespace="http://www.clublog.org/cty/v1.1" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="clublog">
    <xs:complexType>
      <xs:sequence>

        <xs:element name="entities">
          <xs:complexType>
            <xs:sequence>
              <xs:element maxOccurs="unbounded" name="entity">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element name="adif" type="xs:decimal" />
                    <xs:element name="name" type="xs:string" />
                    <xs:element name="prefix" type="xs:string" />
                    <xs:element name="deleted" type="xs:boolean" />
                    <xs:element name="cqz" type="xs:unsignedByte" />
                    <xs:element name="cont" type="xs:string" />
                    <xs:element name="long" type="xs:decimal" />
                    <xs:element name="lat" type="xs:decimal" />
                    <xs:element minOccurs="0" name="start" type="xs:dateTime" />
                    <xs:element minOccurs="0" name="end" type="xs:dateTime" />
                    <xs:element minOccurs="0" name="whitelist" type="xs:boolean" />
                    <xs:element minOccurs="0" name="whitelist_start" type="xs:dateTime" />
                    <xs:element minOccurs="0" name="whitelist_end" type="xs:dateTime" />
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>

        <xs:element name="exceptions">
          <xs:complexType>

我对实体节点以外的任何东西都不感兴趣。其中最多有 400 个,而例外情况则有数千个。 我到目前为止的代码是

using (WebClient wc = new WebClient())
{
     wc.DownloadFile("https://secure.clublog.org/cty.php?api="API","Test.gz");

           var doc = new HtmlAgilityPack.HtmlDocument();

           using (var file = File.Open("Test.gz", FileMode.Open))
           using (var zip = new GZipStream(file, CompressionMode.Decompress))
           {
               doc.Load(zip);
           }

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

就是这样。当然 HTML Agility 包没有文档,我对解析 XML 代码的理解有限。

这就是我所在的位置: XD 包含有效的 xml 数据。

    private void button1_Click(object sender, EventArgs e)
    {
        var dict = (Dictionary<string, decimal>)null;
        using (WebClient wc = new WebClient())
        {

            wc.DownloadFile("https://secure.clublog.org/cty.php?api=", "Test.gz");


            using (var file = File.Open("Test.gz", FileMode.Open))
            {
                using (var zip = new GZipStream(file, CompressionMode.Decompress))
                {

                    using (var xmlReader = XmlReader.Create(zip))
                    {
                        //                            Dictionary<string, decimal> dict = new Dictionary<string, decimal>();

                        var xd = XDocument.Load(xmlReader);


                    }

所以这里是 xml 数据....两条记录。我试图将文件保存在我的服务器上,但它不会让我...

<?xml version="1.0" encoding="utf-8" ?>
-<clublog xmlns="http://www.clublog.org/cty/v1.0" date="2014-03-16T08:30:03+00:00">
  -<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>

【问题讨论】:

  • 为什么使用 HTML Agility Pack 来解析 XML?
  • 您能否提供您要解析的实际 XML 的示例?

标签: c# xml html-agility-pack


【解决方案1】:

这样的东西应该适合你:

var dict = (Dictionary<string, decimal>)null;
using (WebClient wc = new WebClient())
{
    var text = wc.DownloadString(
        "https://secure.clublog.org/cty.php?api=" + API);
    using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(text)))
    {
        using (var zip = new GZipStream(stream, CompressionMode.Decompress))
        {
            using (var xmlReader = XmlReader.Create(zip))
            {
                var xd = XDocument.ReadFrom(xmlReader);
                dict =
                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 => x.Element(XName.Get("name", "http://www.clublog.org/cty/v1.0")).Value,
                        x => (decimal)x.Element(XName.Get("adif", "http://www.clublog.org/cty/v1.0")));
            }
        }
    }
}

我假设您实际上想要 Dictionary&lt;string, decimal&gt; 给定“adif”的类型,但如果我错了,它应该很容易更改。

我的方法避免了所有的文件问题。

【讨论】:

  • 嗨,我试过你的代码,并在行使用 (var xmlReader = XmlReaderCreate(zip) 我收到 InvalidDataException 错误“GZip 标头中的幻数不正确)。如果我尝试使用我的基于文件的代码然后我收到一个关于幻数的错误。
  • 糟糕,抱歉。如果我使用基于 filew 的代码,那么我会收到一个错误,即 xmlready 必须是交互式的?谢谢
  • @Tom 我认为您在使用这两种解决方案时遇到的问题在于 xml 数据是 UTF-16。据我所知,你必须转换它,UTF-8 是理想的。您可以阅读this post 了解更多信息。
  • 嗨,也许我使用文件的代码工作正常。如果我用 var xd = XDOcument.Load(xmlReader) 替换 var xd = XDocument.ReadFrom(xmlReader) 我摆脱了 xmlreader 必须是交互式的错误。那时我有 xd ,其中包含一个完全有效的未压缩 xml 文档。但是此时,上面的代码不起作用。它告诉我 dict = xd.... 中有一个空引用。
  • @Tom - 尝试将内存流编码更改为“UTF16”。
【解决方案2】:

Jenkies。我刚刚为另一个问题写了一个很好的答案,就像这样。如果您可以使用 .NET 3.5,则可以使用 linq-to-xml,这将大大简化此操作。

让我们开始吧。首先,您需要加载文档。看看herehere 以获得一些帮助。我认为第二个对你的帮助更大。

现在开始挖掘了。由于您对可能只有几层深的节点感兴趣,因此这应该不会太痛苦。在这一点上,我们遇到了 2 种设计(我能想到的),逐层削去并将其炸成小块。由于您正在处理大量数据,因此切片可能会更快,也可能不会。因此,我将包括这两种设计,并让您从那里进行测试。

此设计将假设doc 代表整个 xml 文档。

削片方法:

var elements = doc.Elements(xs:element).Where(el =&gt; el.Attribute("name").Value == "entities");

从那里使用Elements()Attributes() 的组合应该是一件简单的事情。

爆破方法只是将Elements() 替换为Descendants()。如果您正在处理近根级别的节点,我会坚持使用切片方法。

现在将其放入DictionaryThis 应该为您指明正确的方向。这对我来说肯定派上用场了。

【讨论】:

  • 这些都不起作用。我至少花了 5 个小时尝试其他事情。为什么需要有这么多方法来做同样的事情,那么复杂?
  • 这允许个人喜好。 :)
  • 我很好奇,这个文件存放在哪里?它是本地的、网络上的还是互联网上的?
  • 文件来源于网络。之后存储在本地。
  • 任何人请!我在这上面浪费了一整天,从网上尝试了几十个例子,但都没有成功。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多