2015-06-08 125 views
0

我有一个XML文件,我想用LINQ解析,以获得包含属性ID的所有节点。通过这个ID,该节点的名称和它的祖父母的名字,我想在LINQ查询中创建一个新对象(类型为EveItem)。LINQ到XML查询Where()函数不返回任何东西

这里是我的XML文件的一部分给它是如何构建的例子:

<?xml version="1.0" encoding="UTF-8"?> 
<Eve_App> 
    <Item_Types> 
     <Ore> 
      <Arkonor_Category> 
       <Arkonor ID="22"/> 
       <Compressed_Arkonor ID="28367"/> 
       <Compressed_Crimson_Arkonor ID="28385"/> 
       <Compressed_Prime_Arkonor ID="28387"/> 
       <Crimson_Arkonor ID="17425"/> 
       <Prime_Arkonor ID="17426"/> 
      </Arkonor_Category> 

      <Bistot_Category> 
       <Bistot ID="1223"/> 
       <Compressed_Bistot ID="28388"/> 
       <Compressed_Monoclinic_Bistot ID="28389"/> 
       <Compressed_Triclinic_Bistot ID="28390"/> 
       <Monoclinic_Bistot ID="17429"/> 
       <Triclinic_Bistot ID="17428"/> 
      </Bistot_Category> 

      <Crokite_Category> 
       <Compressed_Crokite ID="28391"/> 
       <Compressed_Crystalline_Crokite ID="28392"/> 
       <Compressed_Sharp_Crokite ID="28393"/> 
       <Crokite ID="1225"/> 
       <Crystalline_Crokite ID="17433"/> 
       <Sharp_Crokite ID="17432"/> 
      </Crokite_Category> 

      <Dark_Ochre_Category> 
       <Compressed_Dark_Ochre ID="28394"/> 
       <Compressed_Obsidian_Ochre ID="28395"/> 
       <Compressed_Onyx_Ochre ID="28396"/> 
       <Dark_Ochre ID="1232"/> 
       <Obsidian_Ochre ID="17437"/> 
       <Onyx_Ochre ID="17436"/> 
      </Dark_Ochre_Category> 
      ... 
     </Ore> 

     <Ice> 
      <Ice> 
       <Blue_Ice ID="16264"/> 
       <CLear_Icicle ID="16262"/> 
       <Compressed_Blue_Ice ID="28433"/> 
       <Compressed_Clear_Icicle ID="28434"/> 
       <Compressed_Dark_Glitter ID="28435"/> 
       <Compressed_Enriched_Clear_Icicle ID="28436"/> 
       <Compressed_Gelidus ID="28437"/> 
       <Compressed_Glacial_Mass ID="28438"/> 
       <Compressed_Glare_Crust ID="28439"/> 
       <Compressed_Krystallos ID="28440"/> 
       <Compressed_Pristine_White_Glaze ID="28441"/> 
       <Compressed_Smooth_Glacial_Mass ID="28442"/> 
       <Compressed_Thick_Blue_Ice ID="28443"/> 
       <Compressed_White_Glaze ID="28444"/> 
       <Dark_Glitter ID="16267"/> 
       <Enriched_Clear_Icicle ID="17978"/> 
       <Gelidus ID="16268"/> 
       <Glacial_Mass ID="16263"/> 
       <Glare_Crust ID="16266"/> 
       <Krystallos ID="16269"/> 
       <Pristine_White_Glaze ID="17976"/> 
       <Smooth_Glacial_Mass ID="17977"/> 
       <Thick_Blue_Ice ID="17975"/> 
       <White_Glaze ID="16265"/> 
      </Ice> 
     </Ice> 
     ... 

我曾尝试下面的查询做我想做的事,但不幸的是,这是行不通的:

items = _xmlFile.Descendants(itemType.ToString()) 
        .Where(x => x.Attribute("ID") != null) // This part returns nothing 
        .Select(x => new EveItem(x.Name.LocalName, 
         (uint)x.Attributes().FirstOrDefault(a => a.Name.LocalName == "ID"), 
         (EveItem.ItemTypes)itemType)).ToList(); 

当我调试在Visual Studio这个查询,我可以看到_xmlFile.Descendants(itemType.ToString())返回我的XML文件的好子树,但查询的.Where(x => x.Attribute("ID") != null)部分不返回任何东西(所以.Select(..)不得到执行任何东西)。我试图通过这个Where(..)子句得到的是实际上在其中声明了属性ID的所有节点。

我在这个查询中做错了什么?

编辑:

我试图从呼叫的itemType.ToString()_xmlFile.Descendants()和它现在的作品,但我得到的是有一个ID而不是属性只有在正确的itemType节点下的人的所有项目(矿石,冰等)。

这是为什么发生?在调试中,我确实看到_xmlFile.Descendants(itemType.ToString())调用返回正确的XML结构。

回答

2

这是因为没有你的物品类型节点(矿石,冰等)具有ID属性。属性是在项目类型节点的后裔,因此要尽量添加.Descendants()方法调用,就像这样:

items = _xmlFile.Descendants(itemType.ToString()) 
       .Descendants() //get descendants of current item type 
       .Where(x => x.Attribute("ID") != null) 
       .Select(x => new EveItem(
           x.Name.LocalName, 
           (uint)x.Attributes().FirstOrDefault(a => a.Name.LocalName == "ID"), 
           (EveItem.ItemTypes)itemType 
          ) 
         ) 
       .ToList(); 
+0

这工作。虽然我仍然不明白为什么我必须添加另一个'.Descendants()'。不.'Descendants()'发回所有传递给它的节点的子元素?所以是的,我的矿石,冰等节点没有任何'ID'属性,但它应该检查他们的孩子,孙子等,直到叶节点没有?那是我对功能如何起作用的理解,我错了吗? – Choub890

+1

不,你一定很困惑。这里'.Descendants(itemType.ToString())',* descendant *是'_xmlFile' *的后代,它的名字是'itemType.ToString())'。 – har07

+1

你确实是对的。我只是检查了msdn文档并了解了两个函数调用(带参数和不带参数)之间的区别。感谢您指出了这一点! – Choub890

相关问题