简体   繁体   English

C#从xml文件读取某些元素/属性

[英]C# Reading certain element / attribute from xml file

Im trying to read a certain attributes from following xml file (as console program) 我试图从以下xml文件中读取某些属性(作为控制台程序)

http://api.openweathermap.org/data/2.5/forecast?q=lahti,fin&mode=xml http://api.openweathermap.org/data/2.5/forecast?q=lahti,fin&mode=xml

As you see inside 'forecast' element there are multiple 'time' elements. 正如您在“预测”元素中看到的那样,有多个“时间”元素。 What I want is to pick certain 'time' element and then pick given thing inside of it (lets say 'symbol' ) and print all/any attributes it has. 我想要的是选择某些“时间”元素,然后选择其中的给定事物(让我们说“ symbol” ),并打印出它具有的所有/任何属性。

I want to be able to control which 'time' element I pick and which attributes I want to print. 我希望能够控制选择的“时间”元素以及要打印的属性。

This far all I have managed to do is to print every 'time' element and their attributes and also I managed to print every attribute inside of given 'time' element. 我到目前为止要做的只是打印每个“时间”元素及其属性,而且我设法在给定的“时间”元素内打印每个属性。 But I just can't figure how to control it. 但我只是不知道如何控制它。

With the following code, I can print everything inside the first 'time' element. 使用以下代码,我可以在第一个“时间”元素中打印所有内容。 Item(0) is the index of element and the for loop makes sure that I don't get empty lines. Item(0)是元素的索引,并且for循环可确保我不会出现空行。 As you can see from xml file, some 'time' elements has different amount of attributes inside of them so I guess I need to call them By name insted of index. 正如您从xml文件中看到的那样,某些“时间”元素在其中具有不同数量的属性,因此我想我需要通过按索引的名称来调用它们。

    static void xmlReader()
    {
        int i;

        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.Load(parseLink());

        foreach (XmlNode xmlNode in xmlDoc.DocumentElement.GetElementsByTagName("time").Item(0))
            for (i = 0; i < xmlNode.Attributes.Count; i++)
            {
                Console.WriteLine(xmlNode.Attributes[i].Value);
            }
        Console.ReadKey();

    }

Use Linq2Xml, it's much easier and convenient. 使用Linq2Xml,它更加轻松便捷。

public static void Main()
{
    var forecast = XDocument.Load(@"http://api.openweathermap.org/data/2.5/forecast?q=lahti,fin&mode=xml")
                            .Root
                            .Element("forecast");

    foreach (var time in forecast.Elements("time")
                                 .Where(e => e.Element("clouds")
                                              .Attribute("value")
                                              .Value == "overcast clouds"))
    {
        Console.WriteLine(time.Element("symbol").Attribute("name").Value);
    }
}

You can use XmlReader ( tutorial ) as flowing, 您可以使用XmlReader教程 )来顺其自然,

Here I get from attribute from time element and name attribute sybol element.. And they are for same Time element. 在这里,我得到from从属性, time要素和name属性sybol元素。而他们是同一时间的元素。 Also added extracting example for value of cloud 还添加了云价值提取示例

 using (XmlReader reader = XmlReader.Create(@"http://api.openweathermap.org/data/2.5/forecast?q=lahti,fin&mode=xml"))
 {
      // Walk through all Elements 
      while (reader.Read())
      {
         // If we meet time element ; go inside and walk 
         if (reader.Name == "time")
         {
               Console.WriteLine("A new TIME ");

               // Extract from attribute
               String from = reader["from"];
               if (from != null)
               {
                    Console.WriteLine("\t From : " + from);
               }

               // Now walk through all elements inside same Time element
               // Here I use do-while ; what we check is End element of time : </time> .. when we walk till we meet </time> we are inside children of same Time
               // That mean we start from <time> and walk till we meet </time>
               do
               {
                    reader.Read();

                    if (reader.Name == "symbol")
                    {
                         // You can use this approach for any Attribute in symbol Element
                         String name = reader["name"];
                         if (name != null)
                         {
                              Console.WriteLine("\t Symbol name :" + name);
                         }
                    }

                    if (reader.Name == "clouds")
                    {
                         String clouds = reader["value"];
                         if (clouds != null)
                         {
                           Console.WriteLine("\t\t Clouds value : " + clouds);
                         }
                     }

              } while (reader.NodeType != XmlNodeType.EndElement && reader.Name != "time");

          }
      }
}

Simply try this on your Console program.. 只需在控制台程序上尝试即可。

Similar @aush's response, but with some formatting @aush的响应类似,但具有一些格式

        var doc = XDocument.Load(@"http://api.openweathermap.org/data/2.5/forecast?q=lahti,fin&mode=xml");
        var forecastEl = doc.Root.Element(XName.Get("forecast"));

        var timeNodes = from e in forecastEl.Elements("time")
                       where e.Element("symbol")
                            .Attribute(XName.Get("name"))
                            .Value == "light snow"
                       select e;

        var colFormat = "{0,-20} {1,-20} {2,-30}";
        Console.WriteLine(colFormat, "TimeFrom", "TimeTo", "SymbolName");
        foreach(var time in timeNodes)
            Console.WriteLine(colFormat
                , time.Attribute("from").Value
                , time.Attribute("to").Value
                , time.Element("symbol").Attribute("name").Value);

Results: 结果:

TimeFrom             TimeTo               SymbolName 
2015-03-07T12:00:00  2015-03-07T15:00:00  light snow 
2015-03-07T15:00:00  2015-03-07T18:00:00  light snow

Using XDocument is a bit easier here... 在这里使用XDocument比较容易...

private static void XmlOutput()
    {
        var filePathAndName = @"http://api.openweathermap.org/data/2.5/forecast?q=lahti,fin&mode=xml";
        var xmlDoc = XDocument.Load(filePathAndName);

        // Get list of Nodes matching the "time" name or any other filters you wish.
        var nodes = xmlDoc.Descendants().Where(nd => nd.Name.LocalName == "time");

        // Filter the node list to only those where the date is as specified (and any other filters you wish).
        // This could be done in the initial linq query - just making it clearer here.
        nodes = nodes.Where(nd => nd.Attributes().Any(cnd => cnd.Name.LocalName == "from" && cnd.Value.Contains("2015-03-07")));

        foreach (XElement element in nodes)
        {
            // For each descendant node where named "symbol"... 
            foreach(var node in element.Descendants().Where(nd => nd.Name.LocalName == "symbol"))
            {
                // Write out these particular attributes ("number" and "name")
                string output = "";
                output += node.Attributes().FirstOrDefault(nd => nd.Name.LocalName == "number").Value;
                output += ", " + node.Attributes().FirstOrDefault(nd => nd.Name.LocalName == "name").Value;
                Console.WriteLine(output);
            }
        }

        Console.ReadKey();
    }

Using my xml library here , you can search for an actual DateTime value like this: 在这里使用我的xml ,您可以像这样搜索实际的DateTime值:

XElement root = XElement.Load(@"http://api.openweathermap.org/data/2.5/forecast?q=lahti,fin&mode=xml");

var search = DateTime.Parse("2015-03-07T21:00:00");

XElement time = root.XPathElement("//time[@from >= {0} and @to > {1}]", search, search);

var value = time.ToString();

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM