답변:
후손은 절대적으로 잘 작동해야합니다. 예를 들면 다음과 같습니다.
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" />
doc.Descendants("Cars").Descendants("Part")
(또는 아마도 .Elements("Part")
직계 자녀 인 경우에만 가능)
var foo = new XDocument().Descendants("Bar").Descendants("Baz");
하기 때문에 Descendants
반환 빈 IEnumerable<XElement>
하지 null
.
네임 스페이스를 나타내는 예제 :
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
이름별로 비교 하려면 사용해야 합니다.
자손은 필요한 것을 정확하게 수행하지만 요소 이름과 함께 네임 스페이스 이름을 포함했는지 확인하십시오. 생략하면 빈 목록이 표시 될 수 있습니다.
이를 달성하는 두 가지 방법이 있습니다.
다음은 이러한 접근 방식을 사용하는 샘플입니다.
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");
결과는 널 포인터이거나 결과가 없습니다.
XPathEvaluate
됩니다 System.Xml.XPath
.
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);
}
}
}
우리는 위의 사실을 알고 있습니다. 존은 결코 틀리지 않습니다. 실제 소원은 조금 더 갈 수 있습니다
<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을 어떻게 얻을 수 있습니까? 또는 이름이 attrbute 인 요소를 흐리게하는 방법.
1- 네임 스페이스와 아래의 이름으로 액세스하면 찾을 수 있습니다
doc.Descendants().Where(p => p.Name.LocalName == "OTA_AirAvailRQ").Attributes("EchoToken").FirstOrDefault().Value
2- 다음 과 같은 속성 컨텐츠 값으로 찾을 수 있습니다.
이것은 클래스 Linq
의 기반 및 후손 방법 에 대한 솔루션의 변형입니다.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();
}
}
(코드 및 지침은 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());
}
참고 : 콘솔 응용 프로그램 및 WPF 또는 Windows Forms의 경우 "using System.Xml.Linq;"를 추가해야합니다. 콘솔 상단에 프로젝트 상단에 지시문을 사용하면 Using 지시문을 추가하기 전에이 네임 스페이스에 대한 참조를 추가해야합니다. 또한 콘솔의 경우 기본적으로 "속성 폴더"아래에 리소스 파일이 없으므로 리소스 파일을 수동으로 추가해야합니다. 아래의 MSDN 기사에서이를 자세히 설명합니다.