LINQ to XML 递归查询

发布于 2024-11-26 20:30:58 字数 2128 浏览 0 评论 0原文

我有一个 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 个文件夹深,它会失败并且出现空引用异常。这是我正在使用的查询:

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

*和信用到期的信用,我得到这个查询 这里

currentFile 变量的声明中发生了 nullreference 异常,我不确定为什么。我已确保 Guid 匹配...并且由于 fileFromMap 已正确声明,我知道已找到我的文件。我认为这里需要做的是更好地递归检查父文件夹以确保安全。一旦发现任何安全性,查询就可以停止,因为按照站点的设置方式,不应该存在冲突的安全性声明。 (例如,已定义安全性的文件夹中不会包含已定义安全性的文件夹)

如果我错了,并且这不是我需要做的,请提供您可能有的任何建议,并随时更改相应地给出这个问题的标题,以便更好地记录它。

I have an xml sitemap structured like a document tree, such that it looks like this:

<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. The actual xml file is too big to just show. 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.

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. 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. I've made sure that the Guids match up...and since fileFromMap is being declared correctly, I know that my file is being found. 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

花落人断肠 2024-12-03 20:30:58

(如果你在上一个问题中给我留下评论,那可能是最好的,但我现在也可以回答这个问题了;)

我提供的代码中有一个错误:我认为 SelectMany() 以与 XElement.Add() 相同的方式折叠 null 项,但我错了。如果祖先链中存在没有角色的文件夹,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]);
        }));

我将使用反向链接更新我的原始答案。

(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. If there is a folder without roles in the ancestor chain, SelectMany() will throw a NullReferenceException.

We only need to feed it an empty enumerable of XElement to solve the problem:

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文