XDocument: как найти значение атрибута во вложенном xml - PullRequest
0 голосов
/ 19 февраля 2020

Учитывая приведенный ниже фрагмент рабочего кода, я пытаюсь получить элемент target внутри RootChild2.

https://dotnetfiddle.net/eN4xV9

string str =
    @"<?xml version=""1.0""?>  
    <!-- comment at the root level -->  
    <Root>  
        <RootChild1>
            <Child>Content</Child>  
            <Child>Content</Child>  
            <Child>Content</Child>  
        </RootChild1>
        <RootChild2>
            <Child>Content</Child>  
            <Child key='target'>Content</Child>  
            <Child>Content</Child>  
        </RootChild2>
    </Root>";
XDocument doc = XDocument.Parse(str);

foreach (XElement element in doc.Descendants("RootChild2"))
{
    if (element.HasAttributes && element.Element("Child").Attribute("key").Value == "target")
        Console.WriteLine("found it");
    else
        Console.WriteLine("not found");
}

Ответы [ 4 ]

3 голосов
/ 19 февраля 2020

Находит все 3 RootChild2/Child элементов, затем проверяет каждый по очереди:

        foreach (XElement child in doc.Descendants("RootChild2").Elements("Child"))
        {
            if ((string)child.Attribute("key") == "target")
                Console.WriteLine("found it");
            else
                Console.WriteLine("not found");
        }
2 голосов
/ 19 февраля 2020

Вы получаете доступ к самому элементу RootChild2 через element внутри вашего l oop. Взгляните на следующую версию:

        foreach (XElement element in doc.Descendants("RootChild2").Nodes())
        {
            if (element.HasAttributes && element.Attribute("key").Value == "target")
                Console.WriteLine("found it");
            else
                Console.WriteLine("not found");
        }

Теперь она перебирает все узлы RootChild2.

2 голосов
/ 19 февраля 2020

Вам нужно немного переписать свой foreach l oop, добавить доступ к дочерней коллекции Elements() в RootChild2 и проверить каждый элемент в перечислении. Вы также можете проверить наличие атрибута key в элементе, чтобы исключить потенциальное исключение нулевой ссылки

foreach (XElement element in doc.Descendants("RootChild2").Elements())
{
    if (element.HasAttributes && element.Attribute("key")?.Value == "target")
        Console.WriteLine("found it");
    else
        Console.WriteLine("not found");
}

Descendants(XName) возвращает только элементы с совпадающими именами, поэтому вы получаете только один элемент RootChild2 как результат в вашем коде

2 голосов
/ 19 февраля 2020

Здесь есть три проблемы:

  • Вы проверяете, есть ли у элемента RootChild2 какие-либо атрибуты - и он не
  • Вы проверяете только первое Child элемент под каждым RootChild2 элементом
  • Вы предполагаете, что атрибут присутствует (путем разыменования XAttribute)

Вот код, который all найдет целевые элементы в RootChild2:

foreach (XElement element in doc.Descendants("RootChild2"))
{
    var targets = element
        .Elements("Child")
        .Where(child => (string) child.Attribute("key") == "target")
        .ToList();
    Console.WriteLine($"Found {targets.Count} targets");
    foreach (var target in targets)
    {
        Console.WriteLine($"Target content: {target.Value}");
    }            
}

Обратите внимание, что приведение XAttribute к string - это простой способ избежать проблем с нулевыми ссылками - потому что результат явного преобразования равен нулю, когда источник равен нулю. (Это общий шаблон в LINQ для XML.)

...