读取xml文件的多个子节点 [英] Reading multiple child nodes of xml file
问题描述
我创建了一个具有示例内容的Xml文件,如下所示:
I have created an Xml file with example contents as follows:
<?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>
我需要能够读取所选PeriodGroup中的Period节点子级.我想,如果更明智的话,PeriodName可能是Period的属性.
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.
我查看了很多示例,但似乎没有一个是正确的,似乎有数十种不同的方法,有些使用XmlReader,有些使用XmlTextReader,而有些则不使用.因为这是我第一次阅读Xml文件,所以我想问一下是否有人可以给我一个指针.我有一些可以尝试的东西,但是感觉很笨拙.我正在使用VS2010和c#.另外,我看到很多人都在使用LINQ-Xml,因此,我感谢使用此方法的利弊.
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.
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);
}
推荐答案
您可以这样使用XPath方法:
You could use an XPath approach like so:
XmlNodeList xnl = doc.SelectNodes(string.Format("/Periods/PeriodGroup[@name='{0}']/Period", PG));
尽管LINQ比XML更易读,但是更喜欢LINQ.
Though prefer LINQ to XML for it's readability.
这将根据提供的 PeriodGroup
name
属性返回 Period
节点子级,例如 HER
:
This will return Period
node children based on the PeriodGroup
name
attribute supplied, e.g. 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();
结果:
<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>
查询非常简单
from n in xml.Descendants("Periods")
将返回元素 Periods
的后代元素的集合.然后,我们使用 where
根据属性值过滤此节点集合:
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:
where n.Element("PeriodGroup").Attribute("name").Value == "HER"
然后将集合过滤为具有 name
属性且值为 HER
Will then filter down the collection to PeriodGroup
elements that have a name
attribute with a value of HER
最后,我们选择 PeriodGroup
元素并获取其后代节点
Finally, we select the PeriodGroup
element and get it's descendant nodes
select n.Element("PeriodGroup").Descendants().Elements()
编辑(查看评论)
由于此表达式的结果只是一个查询,因此我们使用 .ToList()
枚举集合并返回一个包含所需值的对象.您还可以创建匿名类型来存储元素值,例如:
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:
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;
}
这是查询运行后 nodes
对象的外观:
This is what the nodes
object will look like after the query has run:
这篇关于读取xml文件的多个子节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!