如何获取具有某个属性的节点的所有子节点?

问题描述:

我有一个是这样的一个XML文档:如何获取具有某个属性的节点的所有子节点?

<Menu> 
    <Category name="Comida Rapida"> 
     <Food cocina="si"> 
      <Name>Haburguesa</Name> 
      <Price>10</Price> 
     </Food> 
     <Food> 
      <Name>Papas Fritas</Name> 
      <Price>20</Price> 
     </Food> 
    </Category> 
    <Category name="Bebidas"> 
     <Food> 
      <Name>Pepsi</Name> 
      <Price>30</Price> 
     </Food> 
     <Food cocina="si"> 
      <Name>Coca Cola</Name> 
      <Price>40</Price> 
     </Food> 
    </Category> 
</Menu> 

我想要做的就是通过每<Category>检查,如果该属性是我需要的,例如“BEBIDAS”,所以部分我感兴趣的是:

<Food> 
    <Name>Pepsi</Name> 
    <Price>30</Price> 
</Food> 
<Food cocina="si"> 
    <Name>Coca Cola</Name> 
    <Price>40</Price> 
</Food> 

现在,我有这个,我想要做类似的东西我做了什么已经:

首先我要打印出所有:

Pepsi 30 
Coca Cola 40 

而且我想打印出来只有那些食物有属性cocina="si",所以:

Coca Cola 40 

所以我有各种各样的问题:

首先要使用的方法,我被大量的可能的方法和实现困惑:XmlDocument,XmlReader,XmlTextReader等

this question我收集XmlDocument更容易使用,这将是伟大的,更简单的,th更好的是,因为我可以欣赏到,因此对于解析Xml文件来说,这是相当新的。

我们在实际执行中,我已经尝试了所有种类的东西没有太大的更迭,我似乎能够做一些部分而不是全部一起。

XmlNodeList elemList = doc.GetElementsByTagName("Category"); 
for (int i = 0; i < elemList.Count; i++) 
{ 
    Console.WriteLine(elemList[i].InnerXml); 
} 

这将输出:

<Food><Name>Haburguesa</Name><Price>10</Price></Food><Food><Name>Papas Fritas</Name><Price>20</Price></Food> 
<Food><Name>Pepsi</Name><Price>30</Price></Food><Food><Name>Coca Cola</Name><Price>40</Price></Food> 

这是合理的,但现在,我该如何检查,如果类具有属性name="cocina"

我猜是这样可以帮助:

for (int j = 0; j < elemList[i].Attributes.Count; j++) 
{ 
    //??     
} 

但我无法找到像XmlTextReader的MoveToAttribute()

再然后,我该如何检查是否具有属性cocina="si"

我认为LINQ到XML是这里最简单的方法:

你必须在这里使用XDocument类。从字符串加载文件 - - 采用静态方法XDocument.Parse(DOCUMENT)创建文档对象或XDocument.Load(PATH) - 从给定路径文件加载文档。

之后,你可以很容易地找到你是一个这样的查询找什么:

var doc = XDocument.Parse("<Menu> ... </Menu>"); 
var results = doc.Descendants("Category") 
       .Where(cat => (string)cat.Attribute("name") == "Bebidas") 
       .SelectMany(cat => cat.Elements("Food")) 
       .Where(food => (string)food.Attribute("cocina") == "si") 
       .Select(food => string.Format("{0} {1}", food.Element("Name"), food.Element("Price"))).ToList(); 

为了更清楚我会尽力来形容该查询并:

  1. 将名为“Category”的所有元素作为文档根元素的后代
  2. 仅选择该类别,其中“name”属性的值为“Bebidas”
  3. 项目该类别中的“食品”元素融入其中收集与“COCINA”属性值等于“SI”
  4. 项目导致元素融入格式化字符串
  5. 选择“食物”元素“的名字 - 价格”
+0

谢谢我正在尝试它! – Trufa

+0

我冒昧并更改了Format的格式。 – Trufa

+0

我有一个问题,但我不知道如何使用'结果'。每个人都不应该做一个简单的事情吗另外,如果我正在阅读文件,我应该使用XDocument.Load()对吗? – Trufa

你应该使用XPATH,而不是编写代码来检索这些节点。

要XPath表达式是 “//食品[@cocina = 'SI']”

IE使用doc.selectNodes(xpath的)作为使用XPath的方式,良好的浏览器使用doc.evaluate() 。

到这里看看:http://www.w3schools.com/xpath/xpath_examples.asp

+0

我来看看,谢谢。 – Trufa

LINQ to XML很好,但可能会变得很乱。如果你打算使用XML,你应该知道如何使用XPath来过滤你需要的节点。

试试这个:

foreach (XmlNode node in doc.SelectNodes("//Food[@cocina = 'si']")) 
{ 
    Console.WriteLine(node.SelectSingleNode("Name").InnerText 
     + " " 
     + node.SelectSingleNode("Price").InnerText); 
} 

的XPath到处都是支持的;在.NET之外,LINQ to XML对你来说并不好。