어떤 깊이에서든 이름으로 요소에 대한 XDocument 쿼리
나는이 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
A는 XDocument
.
이 속성 Name
은 a LocalName
및 a 가있는 객체를 반환합니다 Namespace
. 따라서 Name.LocalName
이름별로 비교 하려면 사용해야 합니다.
Descendants will do exactly what you need, but be sure that you have included a namespace name together with element's name. If you omit it, you will probably get an empty list.
There are two ways to accomplish this,
- Linq-to-xml
- XPath
The following are samples of using these approaches,
List<XElement> result = doc.Root.Element("emails").Elements("emailAddress").ToList();
If you use XPath, you need to do some manipulation with the IEnumerable:
IEnumerable<XElement> mails = ((IEnumerable)doc.XPathEvaluate("/emails/emailAddress")).Cast<XElement>();
Note that
var res = doc.XPathEvaluate("/emails/emailAddress");
results either a null pointer, or no results.
I am using XPathSelectElements
extension method which works in the same way to XmlDocument.SelectNodes
method:
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);
}
}
}
}
Following @Francisco Goldenstein answer, I wrote an extension method
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);
}
}
}
we know the above is true. Jon is never wrong; real life wishes can go a little further
<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>
For example, Usually the problem is, how can we get EchoToken in the above xml document? Or how to blur the element with the name attrbute.
1- You can find them by accessing with the namespace and the name like below
doc.Descendants().Where(p => p.Name.LocalName == "OTA_AirAvailRQ").Attributes("EchoToken").FirstOrDefault().Value
2- You can find it by the attribute content value, like this one
This my variant of the solution based on Linq
and Descendants method of the XDocument
class
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();
}
}
For more details on the Desendants
method take a look here.
(Code and Instructions is for C# and may need to be slightly altered for other languages)
This example works perfect if you want to read from a Parent Node that has many children, for example look at the following 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>
Now with this code below (keeping in mind that the XML File is stored in resources (See the links at end of snippet for help on resources) You can obtain each email address within the "emails" tag.
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());
}
Results
- jdoe@set.ca
- jsmith@hit.ca
- rgreen@set_ig.ca
Note: For Console Application and WPF or Windows Forms you must add the "using System.Xml.Linq;" Using directive at the top of your project, for Console you will also need to add a reference to this namespace before adding the Using directive. Also for Console there will be no Resource file by default under the "Properties folder" so you have to manually add the Resource file. The MSDN articles below, explain this in detail.
How to: Add or Remove Resources
참고URL : https://stackoverflow.com/questions/566167/query-an-xdocument-for-elements-by-name-at-any-depth
'Programing' 카테고리의 다른 글
네임 스페이스가 인식되지 않습니다 (있는 경우에도) (0) | 2020.06.21 |
---|---|
GIT에서 부분 복귀를 할 수 있습니까 (0) | 2020.06.21 |
사이트 코더 바이트에서 'gets (stdin)'은 어떻게됩니까? (0) | 2020.06.21 |
PHP에서 배열의 시작 부분에 항목을 삽입하는 방법은 무엇입니까? (0) | 2020.06.21 |
Java에서 와일드 카드 문자열과 일치하는 파일을 찾는 방법은 무엇입니까? (0) | 2020.06.21 |