LINQ to XML查询兄弟元素

时间:2011-07-25 19:44:28

标签: c# .net xml linq linq-to-xml

很抱歉,如果这个问题非常基础,但我没有使用过XML,这是我第一次使用LINQ to XML ...

我有一个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>
</Site>

通过这种方式,每个文件都将从其父文件夹(或祖父文件夹等)继承安全性,具体取决于<security></security>所在的树的距离。

我希望能够在给定文件的GUID的情况下,使用LINQ选择该文件,并收集与文件已继承的安全性相关联的所有角色。

这是我到目前为止所做的,但这是一次非常艰难的尝试,而且还不完整:

XDocument sitemap = XDocument.Load(@"\sitemap.xml");
XElement currentFile = new XElement("File", 
        from file in sitemap.Elements("File")
        where file.Element("GUID").Equals(guid)
        select file.Parent.Element("security").Elements("role"));

PS。站点地图文件与编写此代码的类位于同一目录中

2 个答案:

答案 0 :(得分:2)

看起来你想走上文件夹祖先链并累积你沿途找到的角色。您可以使用恰当命名的Ancestors()SelectMany()方法执行此操作:

XElement fileFromMap = sitemap.Descendants("File").Where(
    file => file.Attribute("GUID").Value == guid.ToString("D")).Single();

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]);
        }));

编辑:更改了元素大小以匹配更新后的问题。

编辑2:上面的代码错误地将null项目投放到SelectMany()(在这方面远不如XElement.Add()放纵),并且这resulted in a NullPointerException。它已更新为返回空XElement数组。

答案 1 :(得分:0)

试试这个(我通常做方法语法,但你应该能够转换为查询语法)

        XElement currentFile = new XElement("File",
            sitemap.Descendants("file").Where(
               file => file.Attribute("GUID").Value.Equals(guid)).Select(
                   file => file.Parent.Element("security").Elements("role")));

这里currentFile应该有

<File>
  <role>Admin</role>
</File>