어떤 깊이에서든 이름으로 요소에 대한 XDocument 쿼리 싶습니다. 을 사용할 때 Descendants(“element_name”)현재

나는이 XDocument개체를. LINQ를 사용하여 특정 깊이의 특정 이름을 가진 요소를 쿼리하고 싶습니다. 을 사용할 때 Descendants("element_name")현재 수준의 직접적인 하위 요소 만 얻습니다. 내가 찾고있는 것은 XPath의 “// element_name”과 같습니다. 방금 사용해야합니까 XPath, 아니면 LINQ 메소드를 사용하여 수행 할 수 있습니까? 감사.



답변

후손은 절대적으로 잘 작동해야합니다. 예를 들면 다음과 같습니다.

using System;
using System.Xml.Linq;

class Test
{
    static void Main()
    {
        string xml = @"
<root>
  <child id='1'/>
  <child id='2'>
    <grandchild id='3' />
    <grandchild id='4' />
  </child>
</root>";
        XDocument doc = XDocument.Parse(xml);

        foreach (XElement element in doc.Descendants("grandchild"))
        {
            Console.WriteLine(element);
        }
    }
}

결과 :

<grandchild id="3" />
<grandchild id="4" />


답변

네임 스페이스를 나타내는 예제 :

String TheDocumentContent =
@"
<TheNamespace:root xmlns:TheNamespace = 'http://www.w3.org/2001/XMLSchema' >
   <TheNamespace:GrandParent>
      <TheNamespace:Parent>
         <TheNamespace:Child theName = 'Fred'  />
         <TheNamespace:Child theName = 'Gabi'  />
         <TheNamespace:Child theName = 'George'/>
         <TheNamespace:Child theName = 'Grace' />
         <TheNamespace:Child theName = 'Sam'   />
      </TheNamespace:Parent>
   </TheNamespace:GrandParent>
</TheNamespace:root>
";

XDocument TheDocument = XDocument.Parse( TheDocumentContent );

//Example 1:
var TheElements1 =
from
    AnyElement
in
    TheDocument.Descendants( "{http://www.w3.org/2001/XMLSchema}Child" )
select
    AnyElement;

ResultsTxt.AppendText( TheElements1.Count().ToString() );

//Example 2:
var TheElements2 =
from
    AnyElement
in
    TheDocument.Descendants( "{http://www.w3.org/2001/XMLSchema}Child" )
where
    AnyElement.Attribute( "theName" ).Value.StartsWith( "G" )
select
    AnyElement;

foreach ( XElement CurrentElement in TheElements2 )
{
    ResultsTxt.AppendText( "\r\n" + CurrentElement.Attribute( "theName" ).Value );
}


답변

이 방법으로 할 수 있습니다 :

xml.Descendants().Where(p => p.Name.LocalName == "Name of the node to find")

어디 xml있어XDocument .

이 속성 Name은 a LocalName및 a 가있는 객체를 반환합니다 Namespace. 따라서 Name.LocalName이름별로 비교 하려면 사용해야 합니다.


답변

자손은 필요한 것을 정확하게 수행하지만 요소 이름과 함께 네임 스페이스 이름을 포함했는지 확인하십시오. 생략하면 빈 목록이 표시 될 수 있습니다.


답변

이를 달성하는 두 가지 방법이 있습니다.

  1. Linq-to-xml
  2. XPath

다음은 이러한 접근 방식을 사용하는 샘플입니다.

List<XElement> result = doc.Root.Element("emails").Elements("emailAddress").ToList();

XPath를 사용하는 경우 IEnumerable을 사용하여 약간의 조작을 수행해야합니다.

IEnumerable<XElement> mails = ((IEnumerable)doc.XPathEvaluate("/emails/emailAddress")).Cast<XElement>();

참고

var res = doc.XPathEvaluate("/emails/emailAddress");

결과는 널 포인터이거나 결과가 없습니다.


답변

XPathSelectElements방법과 같은 방식으로 작동 하는 확장 방법을 사용하고 있습니다 XmlDocument.SelectNodes.

using System;
using System.Xml.Linq;
using System.Xml.XPath; // for XPathSelectElements

namespace testconsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            XDocument xdoc = XDocument.Parse(
                @"<root>
                    <child>
                        <name>john</name>
                    </child>
                    <child>
                        <name>fred</name>
                    </child>
                    <child>
                        <name>mark</name>
                    </child>
                 </root>");

            foreach (var childElem in xdoc.XPathSelectElements("//child"))
            {
                string childName = childElem.Element("name").Value;
                Console.WriteLine(childName);
            }
        }
    }
}


답변

@Francisco Goldenstein의 답변에 따라 확장 방법을 작성했습니다.

using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

namespace Mediatel.Framework
{
    public static class XDocumentHelper
    {
        public static IEnumerable<XElement> DescendantElements(this XDocument xDocument, string nodeName)
        {
            return xDocument.Descendants().Where(p => p.Name.LocalName == nodeName);
        }
    }
}