简体   繁体   English

LINQ to XML 递归查询

[英]LINQ to XML recursive query

I have an xml sitemap structured like a document tree, such that it looks like this:我有一个 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>

*Note that this is NOT my actually xml file. *请注意,这实际上不是我的 xml 文件。 The actual xml file is too big to just show.实际的 xml 文件太大而无法显示。 Basically what you need to take away from this is that there are potentially 'X' amount of folders nested within each other, and at some point in those folders, there can be 'X' amount of files, as well as children folders.基本上,您需要从中删除的是,可能有“X”个文件夹相互嵌套,并且在这些文件夹中的某个时刻,可能有“X”个文件以及子文件夹。

Also, some folders are given security, which is inherited by everything in that folder (files, child folders, files within child folders, etc).此外,某些文件夹具有安全性,该安全性由该文件夹中的所有内容(文件、子文件夹、子文件夹中的文件等)继承。 I am trying to come up with a LINQ to XML query to get the security of a given file based on that files GUID, and it works fine for level-1 and level-2 files, but when I try to run the query on a file that is 3 folders deep, it fails and I get a nullreference exception.我正在尝试提出一个 LINQ to XML 查询,以根据该文件的 GUID 获取给定文件的安全性,它适用于 1 级和 2 级文件,但是当我尝试在3 个文件夹深的文件,它失败并且我得到一个空引用异常。 Here is the query I am using:这是我正在使用的查询:

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

*and credit where credit is due, I got this query here *以及信用到期的信用,我在这里得到了这个查询

The nullreference exception is happening in the declaration of the currentFile variable, and I'm not sure why.currentFile变量的声明中发生了 nullreference 异常,我不知道为什么。 I've made sure that the Guids match up...and since fileFromMap is being declared correctly, I know that my file is being found.我已经确保 Guids 匹配......并且由于fileFromMap被正确声明,我知道我的文件正在被找到。 I assume what needs to be done here is something to better check parent folders recursively for security.我认为这里需要做的是更好地递归检查父文件夹以确保安全。 The query can stop as soon as it finds any security, because the way the site is set up, there should be no conflicting security declarations.查询可以在发现任何安全性后立即停止,因为站点的设置方式不应该存在冲突的安全性声明。 (eg, no folder that has defined security will be within a folder that already has defined security) (例如,已定义安全性的文件夹不会位于已定义安全性的文件夹中)

If I am wrong, and this isn't what I need to do, please offer any suggestions you may have, and feel free to change the title of this question accordingly as to better document it.如果我错了,这不是我需要做的,请提供您可能有的任何建议,并随时相应地更改此问题的标题以更好地记录它。

(It would probably have been best if you left me a comment in your previous question instead, but I might as well answer this one now that it's posted ;) (如果您在之前的问题中给我留言可能会更好,但现在我也可以回答这个问题;)

There's a mistake in the code I provided: I thought SelectMany() collapsed null items in the same way XElement.Add() does, and I was wrong.我提供的代码中有一个错误:我认为SelectMany()以与XElement.Add()相同的方式折叠null项目,但我错了。 If there is a folder without roles in the ancestor chain, SelectMany() will throw a NullReferenceException .如果祖先链中有没有角色的文件夹, SelectMany()将抛出NullReferenceException

We only need to feed it an empty enumerable of XElement to solve the problem:我们只需XElement它提供一个空的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]);
        }));

I'll update my original answer with a backlink.我将使用反向链接更新我的原始答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM