2011-07-26 116 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,不客氣,很高興我可以幫忙:) –