LINQ to XML-запрос для родственных элементов - PullRequest
3 голосов
/ 25 июля 2011

Извините, если этот вопрос очень простой, но я не очень много работал с 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. Файл sitemap находится в том же каталоге, что и класс, в котором написан этот код

Ответы [ 2 ]

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

Похоже, вы хотите пройтись по цепочке предков папок и накопить роли, которые вы найдете на этом пути.Это можно сделать с помощью метко названных 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() в этом отношении)и это привело к NullPointerException.Он был обновлен и теперь возвращает пустой массив XElement.

0 голосов
/ 26 июля 2011

Попробуйте это (обычно я использую синтаксис метода, но вы сможете преобразовать его в синтаксис запроса)

        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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...