【问题标题】:How to parse an XML element that has an attribute inside it? Asp.net C#如何解析其中具有属性的 XML 元素? ASP.NET C#
【发布时间】:2017-09-14 20:36:44
【问题描述】:

XML 文件:

<weatherdata>
<forecast>

<time day="2017-04-18">
    <temperature day="-4.26" min="-6.54" max="-4.26" night="-6.54" eve="-4.26" morn="-4.26"/>
</time>

<time day="2017-04-19">
    <temperature day="3.51" min="-5.41" max="4.49" night="-0.63" eve="4.27" morn="-5.41"/>
</time>

</forecast>
</weatherdata>

我需要根据要使用的 day="xxxx-xx-xx" 解析文件并获取正确的元素。然后,当我有合适的时间时,我想为 temperature_day、temperature_min 等创建具有正确值的新字符串。

我已经尝试了几十个 XmlReader 变体,我想使用它,因为它看起来很简单。这是我到目前为止所拥有的。如果我可以命名“reader.Name ==”,为什么我不能只询问属性名称?

XmlReader reader = XmlReader.Create(URL);
    while (reader.Read())
    {
        if (reader.NodeType == XmlNodeType.Element && reader.Name == "time" && reader.HasAttributes)
        {
            // DATE comes from a asp.net calendar, the format is correct
            if (DATE == reader.GetAttribute("day"))
            {
               if (reader.NodeType == XmlNodeType.Element && reader.Name == "temperature" && reader.HasAttributes)
                {
                    string temperature_day = reader.GetAttribute("day");
                    TextBoxTemp.Text = temperature_day;
                }
            }
        }
    }

我已经用一个非常简单的 XmlReader 代码位测试了 (URL),并确认它可以工作。我现在完全没有想法,元素内部的属性让我感到困惑。

【问题讨论】:

  • 你真的需要使用XmlReader吗? LINQ to XML(XDocument 等)非常更易于使用。
  • 请注意,您的if (... reader.Name == "temperature"...) 条件永远不会为真,因为您已经确定您的阅读器位于Name"time" 的节点上。这就是使用XmlReader 的诀窍——它一次读取一个节点。 @JonSkeet 关于使用 LINQ to XML 的建议很好,甚至使用古老的 XmlDocument 可能更容易掌握。
  • 嗯,不一定。我查看了 XDocument,它看起来比 XmlReader 复杂得多......我想我可以只命名我正在寻找的属性,但显然我不能,除非我做错了什么。
  • “它看起来比 XmlReader 复杂得多” - 真的,真的不是。查询已加载的文档比使用实时解析器要容易很多。关于使用 LINQ to XML 进行查询有 很多 个问题。
  • 然后我会看看 LINQ to XML,谢谢你们@JonSkeet

标签: c# asp.net xml parsing xmlreader


【解决方案1】:

使用 XDocument 代替 XmlReader 更容易查询。

第一个例子

有些代码你也有循环遍历从 LINQ 查询返回的结果。但是由于您只有一个

       // Create XDocument and load in the file
        XDocument _doc = XDocument.Load("C:\\t\\My File2.txt");
        //select all time element where attribute day.Value == to any day you give it just change "2017-04-18" 
        var time = _doc.XPathSelectElements("/weatherdata/forecast/time").Where(c => c.Attribute("day").Value == "2017-04-18");
        // Get IEnumerable of temperatures in the time element
        var temp = time.Select(x => x.Element("temperature"));

        // loop temperatures and get the attribute value from the element
        foreach (var element in temp)
        {
            string day = element.Attribute("day").Value;
            string min = element.Attribute("min").Value;
            string max = element.Attribute("max").Value;
            string night = element.Attribute("night").Value;
            string eve = element.Attribute("eve").Value;
            string morn = element.Attribute("morn").Value;
            MessageBox.Show($"day:{day},\nmin:{min},\nmax:{max},\nnight:{night},\neve:{eve},\nmorn:{morn}");
        }

第二个例子

我得到了查询结果的第一个,因此您不必循环获取一个元素。这有点冒险,因为当没有找到任何元素时,您可以获得空引用异常。但是如果你能在它被抛出之前抓住它,那么简单。

         // Create XDocument and load in the file my case it is the path "C:\\t\\My File2.txt"
        XDocument _doc = XDocument.Load("C:\\t\\My File2.txt");
        // Select all time elements where attribute day.Value == to any day you give it, just change "2017-04-18" 
        // And select the first one of that result as I aspect there is only one time a day
        var time = _doc.XPathSelectElements("/weatherdata/forecast/time").Where(c => c.Attribute("day").Value == "2017-04-18").FirstOrDefault();
        // Get the children of time element by using .Elements() and take the first one of that.
        // You only have one temperature element in a time element so it will take that one with FirstOrDefault();
        var temp = time.Elements().FirstOrDefault();
        // assign attributes values to string
        string day = temp.Attribute("day").Value;
        string min = temp.Attribute("min").Value;
        string max = temp.Attribute("max").Value;
        string night = temp.Attribute("night").Value;
        string eve = temp.Attribute("eve").Value;
        string morn = temp.Attribute("morn").Value;

        // control
        MessageBox.Show($"day:{day},\nmin:{min},\nmax:{max},\nnight:{night},\neve:{eve},\nmorn:{morn}");

“2017-04-18”天的结果:

【讨论】:

  • 我不会关闭它,以防出现意外情况,但似乎这成功了……我现在肯定会更多地研究 LINQ to XML。非常感谢您的帮助以及文档链接。
  • 按需工作,再次感谢您抽出宝贵时间提供帮助!标记为答案
猜你喜欢
  • 2022-12-28
  • 1970-01-01
  • 2012-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多