LINQ to XML рекурсивный запрос - PullRequest
2 голосов
/ 27 июля 2011

У меня есть xml sitemap, структурированный как дерево документов, так что он выглядит так:

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

* и кредит, причитающийся кредит, я получил этот запрос здесь

Исключение nullreference происходит в объявлении переменной currentFile, и я не уверен, почему. Я удостоверился, что Guides совпадают ... и так как fileFromMap объявляется правильно, я знаю, что мой файл найден. Я предполагаю, что здесь нужно что-то сделать, чтобы рекурсивно проверять родительские папки на предмет безопасности. Запрос может быть остановлен, как только он обнаружит какую-либо защиту, поскольку при настройке сайта не должно быть конфликтующих объявлений безопасности. (например, ни одна папка с определенной безопасностью не будет в папке с уже определенной безопасностью)

Если я ошибаюсь, и это не то, что мне нужно делать, пожалуйста, предложите любые ваши предложения и смело изменяйте заголовок этого вопроса соответствующим образом, чтобы лучше его задокументировать.

1 Ответ

2 голосов
/ 27 июля 2011

(Вероятно, было бы лучше, если бы вы оставили мне комментарий в своем предыдущем вопросе, но я мог бы также ответить на этот вопрос сейчас, когда он был опубликован;)

В коде, который я предоставил, есть ошибка: я думал, что 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]);
        }));

Я обновлю свой оригинальный ответ обратной ссылкой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...