codememo

깊이에 상관없이 XDocument에서 이름별 요소 조회

tipmemo 2023. 9. 10. 12:18
반응형

깊이에 상관없이 XDocument에서 이름별 요소 조회

는 을 .XDocument◦. 사용하여 특정 .LINQ를 사용하여 특정 이름을 가진 요소에 대해 깊이에 상관없이 조회하고자 합니다.

Descendants("element_name")는 현재 자식인 , 는 의 인 인 만 만 인 는 인 .XPath에서 "/element_name"에 해당하는 것을 찾고 있습니다.그냥 사용할까요?XPath 방법을 할 수 있는 ① LINQ ② ③ ④ ⑤ 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다음을 가진 객체를 반환합니다.LocalName그리고.Namespace. 그래서 당신이 사용할 수 밖에 없는 것입니다.Name.LocalName이름으로 비교하고 싶다면요.

하위 항목은 필요한 작업을 정확히 수행하지만 요소 이름과 함께 네임스페이스 이름을 포함해야 합니다.생략하면 빈 목록이 나올 것입니다.

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

  1. LINQ에서 XML로
  2. XPath

다음은 이러한 접근법을 사용한 샘플입니다.

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

XPath를 사용하는 경우 IE numberable로 다음과 같은 조작을 수행해야 합니다.

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

참고:

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

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

사용중입니다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);
        }
    }
}

이것은 LINQ에 기반한 솔루션의 나의 변형과 의 Descendants method입니다.XDocument

using System;
using System.Linq;
using System.Xml.Linq;

class Test
{
    static void Main()
    {
        XDocument xml = XDocument.Parse(@"
        <root>
          <child id='1'/>
          <child id='2'>
            <subChild id='3'>
                <extChild id='5' />
                <extChild id='6' />
            </subChild>
            <subChild id='4'>
                <extChild id='7' />
            </subChild>
          </child>
        </root>");

        xml.Descendants().Where(p => p.Name.LocalName == "extChild")
                         .ToList()
                         .ForEach(e => Console.WriteLine(e));

        Console.ReadLine();
    }
}

결과:

Desendants a here서다가다d가e.

우리는 위의 내용이 사실이라는 것을 알고 있습니다.존은 결코 틀리지 않습니다. 실생활의 소망은 조금 더 멀리 갈 수 있습니다.

<ota:OTA_AirAvailRQ
    xmlns:ota="http://www.opentravel.org/OTA/2003/05" EchoToken="740" Target=" Test" TimeStamp="2012-07-19T14:42:55.198Z" Version="1.1">
    <ota:OriginDestinationInformation>
        <ota:DepartureDateTime>2012-07-20T00:00:00Z</ota:DepartureDateTime>
    </ota:OriginDestinationInformation>
</ota:OTA_AirAvailRQ>

예를 들어, 보통 문제는 위의 XML 문서에서 EchoToken을 어떻게 얻을 수 있을까 하는 것입니다.또는 이름 속성으로 요소를 흐리게 하는 방법.

  1. 아래와 같은 네임스페이스와 이름으로 액세스하면 찾을 수 있습니다.

     doc.Descendants().Where(p => p.Name.LocalName == "OTA_AirAvailRQ").Attributes("EchoToken").FirstOrDefault().Value
    
  2. 이것처럼 속성 내용 값으로 찾을 수 있습니다.

(Code and Instructions는 C#용이며 다른 언어의 경우 약간 변경해야 할 수 있습니다.)

이 예제는 자식이 많은 상위 노드에서 읽으려면 완벽하게 작동합니다. 예를 들어 다음 XML을 보십시오.

<?xml version="1.0" encoding="UTF-8"?> 
<emails>
    <emailAddress>jdoe@set.ca</emailAddress>
    <emailAddress>jsmith@hit.ca</emailAddress>
    <emailAddress>rgreen@set_ig.ca</emailAddress> 
</emails>

이제 아래 코드를 사용하여(XML 파일이 리소스에 저장되어 있음을 명심하십시오(리소스에 대한 도움말은 스니펫 끝에 있는 링크 참조) "이메일" 태그 내에서 각 이메일 주소를 얻을 수 있습니다.

XDocument doc = XDocument.Parse(Properties.Resources.EmailAddresses);

var emailAddresses = (from emails in doc.Descendants("emailAddress")
                      select emails.Value);

foreach (var email in emailAddresses)
{
    //Comment out if using WPF or Windows Form project
    Console.WriteLine(email.ToString());

   //Remove comment if using WPF or Windows Form project
   //MessageBox.Show(email.ToString());
}

결과.

  1. jdoe@set.ca
  2. jsmith@hit.ca
  3. rgreen@set_ig.ca

참고: 콘솔 응용 프로그램과 WPF 또는 Windows Forms의 경우 "시스템 사용"을 추가해야 합니다.Xml.Linq;" 프로젝트 맨 위에 지시문을 사용하면 콘솔의 경우 Using 지시문을 추가하기 전에 이 네임스페이스에 대한 참조를 추가해야 합니다.또한 콘솔의 경우 "속성 폴더" 아래에 기본적으로 리소스 파일이 없으므로 수동으로 리소스 파일을 추가해야 합니다.아래 MSDN 기사는 이에 대해 자세히 설명합니다.

리소스 추가 및 편집

방법: 리소스 추가 또는 제거

언급URL : https://stackoverflow.com/questions/566167/query-an-xdocument-for-elements-by-name-at-any-depth

반응형