2011-07-26 73 views
2

我有一个xml结构类似于文档树,使得它看起来像这样:的LINQ to XML的递归查询

<Site> 
<File GUID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx">FileName</file> 
<Folder name="FolderName"> 
    <Security> 
     <Role>Admin</role> 
    </Security> 
    <File GUID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx">FileName</file> 
    <Folder name="subFoler"> 
     <File GUID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx">FileName</file> 
     <File GUID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx">FileName</file> 
     <Folder> 
      <File GUID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx">FileName</file> 
     </Folder> 
    </Folder> 
</Folder> 

*请注意,这是我实际上xml文件。实际的xml文件太大而无法显示。基本上,你需要从中获得的是,可能有'X'数量的文件夹相互嵌套,并且在这些文件夹中的某个点上,可以有'X'数量的文件以及子文件夹。

此外,一些文件夹提供了保证,这是由一切该文件夹中继承(文件,子文件夹,子文件夹内的文件等)。我试图想出一个LINQ to XML查询来获得基于该文件GUID的给定文件的安全性,并且它适用于级别1和级别2文件,但是当我尝试在文件深度为3个文件夹,它失败,我得到一个nullreference异常。下面是我使用的查询:其中信贷是由于

XDocument sitemap = XDocument.Load(HttpContext.Current.Server.MapPath("/.../sitemap.xml")); 
     XElement fileFromMap = 
      sitemap.Descendants("File").Where(
      file => file.Attribute("GUID").Value == guid).First(); 

     XElement currentFile = new XElement("File", 
      fileFromMap.Value, 
      fileFromMap.Ancestors("Folder").SelectMany(
       folder => 
       { 
        XElement security = folder.Element("Security"); 
        return (security != null ? security.Elements("Role") : null); 
       })); 

*和信用,我得到这个查询here

的nullreference异常在currentFile变量的声明发生的事情,我不确定为什么。我确定Guids匹配...并且由于fileFromMap正在被正确声明,我知道我的文件正在被找到。我假设这里需要做的是更好地检查父文件夹的递归安全性。查询可以在发现任何安全性时立即停止,因为该网站的设置方式,应该没有冲突的安全声明。 (例如,没有定义安全性的文件夹将位于已具有定义的安全性的文件夹内)

如果我错了,而且这不是我需要做的,请提供您可能有的任何建议,并感受可以自由更改相应问题的标题以更好地记录它。

回答

2

(它可能早就最好的,如果你离开我的评论在你前面的问题,而不是,但我可能现在,它的发布,以及回答这个问题;)

有一个在我提供的代码的错误:我认为SelectMany()崩溃null项目以相同的方式XElement.Add()呢,我错了。如果在祖先链中没有角色的文件夹,SelectMany()将抛出NullReferenceException

我们只需要养活它的XElement空枚举来解决这个问题:

XElement currentFile = new XElement("File", 
    fileFromMap.Value, 
    fileFromMap.Ancestors("Folder").SelectMany(
     folder => 
     { 
      XElement security = folder.Element("Security"); 
      return (security != null 
        ? security.Elements("Role") : new XElement[0]); 
     })); 

我会用一个反向链接更新我原来的答复。

+0

谢谢!现在它完美地工作了,我想我对LINQ to XML有了更好的理解! PS。我不确定你是否会看到评论,因为我已经接受了答案,但非常感谢你! –

+0

@Jordan,不客气,很高兴我可以帮忙:) –