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
Reading multiple child nodes of xml file
提问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 Period
node children based on the PeriodGroup
name
attribute supplied, e.g. HER
:
这将Period
根据提供的PeriodGroup
name
属性返回节点子节点,例如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 where
to 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 PeriodGroup
elements that have a name
attribute with a value of HER
然后将集合过滤到PeriodGroup
具有name
值为的属性的元素HER
Finally, we select the PeriodGroup
element 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 nodes
object will look like after the query has run:
这是nodes
查询运行后对象的样子:
回答by shakurov
Since the XmlDocument.SelectNodes
method 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);
}
}
}
}
}