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>
*请注意,这不是我实际的 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
(如果你在上一个问题中给我留下评论,那可能是最好的,但我现在也可以回答这个问题了;)
我提供的代码中有一个错误:我认为
SelectMany()
以与XElement.Add()
相同的方式折叠null
项,但我错了。如果祖先链中存在没有角色的文件夹,SelectMany()
将抛出NullReferenceException
。我们只需要向它提供一个空的
XElement
枚举即可解决问题:我将使用反向链接更新我的原始答案。
(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()
collapsednull
items in the same wayXElement.Add()
does, and I was wrong. If there is a folder without roles in the ancestor chain,SelectMany()
will throw aNullReferenceException
.We only need to feed it an empty enumerable of
XElement
to solve the problem:I'll update my original answer with a backlink.