C# 读取xml文件的多个子节点

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15970161/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 18:38:16  来源:igfitidea点击:

Reading multiple child nodes of xml file

c#xmlvisual-studio-2010

提问by Peter C

I have created an Xml file with example contents as follows:

我创建了一个包含示例内容的 Xml 文件,如下所示:

<?xml version="1.0" encoding="utf-8" ?>
<Periods>
  <PeriodGroup name="HER">
    <Period>
      <PeriodName>Prehistoric</PeriodName>
      <StartDate>-500000</StartDate>
      <EndDate>43</EndDate>
    </Period>
    <Period>
      <PeriodName>Iron Age</PeriodName>
      <StartDate>-800</StartDate>
      <EndDate>43</EndDate>
    </Period>
    <Period>
      <PeriodName>Roman</PeriodName>
      <StartDate>43</StartDate>
      <EndDate>410</EndDate>
    </Period>
  </PeriodGroup>
  <PeriodGroup name="CAFG">
    <Period>
      <PeriodName>Prehistoric</PeriodName>
      <StartDate>-500000</StartDate>
      <EndDate>43</EndDate>
    </Period>
    <Period>
      <PeriodName>Roman</PeriodName>
      <StartDate>43</StartDate>
      <EndDate>410</EndDate>
    </Period>
    <Period>
      <PeriodName>Anglo-Saxon</PeriodName>
      <StartDate>410</StartDate>
      <EndDate>800</EndDate>
    </Period>   
  </PeriodGroup>
</Periods>

I need to be able to read the Period node children within a selected PeriodGroup. I guess the PeriodName could be an attribute of Period if that is more sensible.

我需要能够读取选定 PeriodGroup 中的 Period 节点子项。我想 PeriodName 可能是 Period 的一个属性,如果这更明智的话。

I have looked at loads of examples but none seem to be quite right and there seems to be dozens of different methods, some using XmlReader, some XmlTextReader and some not using either. As this is my first time reading an Xml file, I thought I'd ask if anyone could give me a pointer. I've got something working just to try things out, but it feels clunky. I'm using VS2010 and c#. Also, I see a lot of people are using LINQ-Xml, so I'd appreciate the pros and cons of using this method.

我查看了大量示例,但似乎没有一个是完全正确的,而且似乎有几十种不同的方法,有些使用 XmlReader,有些使用 XmlTextReader,有些则不使用。由于这是我第一次阅读 Xml 文件,我想我会问是否有人可以给我一个指针。我有一些工作只是为了尝试一下,但感觉很笨重。我正在使用 VS2010 和 c#。另外,我看到很多人都在使用 LINQ-Xml,所以我很欣赏使用这种方法的利弊。

string PG = "HER";
XmlDocument doc = new XmlDocument();
doc.Load(Server.MapPath("./Xml/XmlFile.xml"));
string text = string.Empty;
XmlNodeList xnl = doc.SelectNodes("/Periods/PeriodGroup");
foreach (XmlNode node in xnl)
{
    text = node.Attributes["name"].InnerText;
    if (text == PG)
    {
        XmlNodeList xnl2 = doc.SelectNodes("/Periods/PeriodGroup/Period");
        foreach (XmlNode node2 in xnl2)
        {
            text = text + "<br>" + node2["PeriodName"].InnerText;
            text = text + "<br>" + node2["StartDate"].InnerText;
            text = text + "<br>" + node2["EndDate"].InnerText;
        }
    }
    Response.Write(text);
}

采纳答案by DGibbs

You could use an XPath approach like so:

您可以像这样使用 XPath 方法:

XmlNodeList xnl = doc.SelectNodes(string.Format("/Periods/PeriodGroup[@name='{0}']/Period", PG));

Though prefer LINQ to XML for it's readability.

虽然更喜欢 LINQ 到 XML,因为它的可读性。

This will return Periodnode children based on the PeriodGroupnameattribute supplied, e.g. HER:

这将Period根据提供的PeriodGroupname属性返回节点子节点,例如HER

XDocument xml = XDocument.Load(HttpContext.Current.Server.MapPath(FileLoc));

var nodes = (from n in xml.Descendants("Periods")
            where n.Element("PeriodGroup").Attribute("name").Value == "HER"
            select n.Element("PeriodGroup").Descendants().Elements()).ToList();

Results:

结果:

<PeriodName>Prehistoric</PeriodName>
<StartDate>-500000</StartDate>
<EndDate>43</EndDate>

<PeriodName>Iron Age</PeriodName>
<StartDate>-800</StartDate>
<EndDate>43</EndDate>

<PeriodName>Roman</PeriodName>
<StartDate>43</StartDate>
<EndDate>410</EndDate>

The query is pretty straightforward

查询非常简单

from n in xml.Descendants("Periods")

Will return a collection of the descendant elements for the element Periods. We then use whereto filter this collection of nodes based on attribute value:

将返回元素的后代元素的集合Periods。然后我们使用where基于属性值过滤这个节点集合:

where n.Element("PeriodGroup").Attribute("name").Value == "HER"

Will then filter down the collection to PeriodGroupelements that have a nameattribute with a value of HER

然后将集合过滤到PeriodGroup具有name值为的属性的元素HER

Finally, we select the PeriodGroupelement and get it's descendant nodes

最后,我们选择PeriodGroup元素并获取它的后代节点

select n.Element("PeriodGroup").Descendants().Elements()

EDIT (See comments)

编辑(见评论)

Since the result of this expression is just a query, we use .ToList()to enumerate the collection and return an object containing the values you need. You could also create anonymous types to store the element values for example:

由于这个表达式的结果只是一个查询,我们使用.ToList()枚举集合并返回一个包含您需要的值的对象。您还可以创建匿名类型来存储元素值,例如:

var nodes = (from n in xml.Descendants("Period").
             Where(r => r.Parent.Attribute("name").Value == "HER")
             select new
             {
                  PeriodName = (string)n.Element("PeriodName").Value,
                  StartDate = (string)n.Element("StartDate").Value,
                  EndDate = (string)n.Element("EndDate").Value
             }).ToList();

//Crude demonstration of how you can reference each specific element in the result
//I would recommend using a stringbuilder here..
foreach (var n in nodes)
{
      text += "<br>" + n.PeriodName;
      text += "<br>" + n.StartDate;
      text += "<br>" + n.EndDate;
}

This is what the nodesobject will look like after the query has run:

这是nodes查询运行后对象的样子:

enter image description here

在此处输入图片说明

回答by shakurov

Since the XmlDocument.SelectNodesmethod actually accepts an XPath expression, you're free to go like this:

由于该XmlDocument.SelectNodes方法实际上接受 XPath 表达式,因此您可以像这样自由地进行:

XmlNodeList xnl = doc.SelectNodes("/Periods/PeriodGroup[@name='" + PG + "']/Period");
foreach (XmlNode node in xnl) {
    // Every node here is a <Period> child of the relevant <PeriodGroup>.
}

You can learn more on XPath at w3schools.

您可以在w3schools了解有关 XPath 的更多信息。

回答by chandu

go thru this

通过这个

 public static void XMLNodeCheck(XmlNode xmlNode)
    {
        if (xmlNode.HasChildNodes)
        {
            foreach (XmlNode node in xmlNode)
            {
                if (node.HasChildNodes)
                {
                    Console.WriteLine(node.Name);
                    if (node.Attributes.Count!=0)
                    {
                        foreach (XmlAttribute att in node.Attributes)
                        {
                            Console.WriteLine("----------" + att.Name + "----------" + att.Value);
                        }
                    }

                    XMLNodeCheck(node);//recursive function 
                }
                else
                {
                    if (!node.Equals(XmlNodeType.Element))
                    {
                        Console.WriteLine(node.InnerText);
                    }

                }
            }
        }
    }