XDocument와 함께 XPath를 사용하는 방법?


109

비슷한 질문이 있지만 제 경우에는 솔루션이 작동하지 않은 것 같습니다. XDocument, XPath 및 네임 스페이스의 이상 함

작업중인 XML은 다음과 같습니다.

<?xml version="1.0" encoding="utf-8"?>
<Report Id="ID1" Type="Demo Report" Created="2011-01-01T01:01:01+11:00" Culture="en" xmlns="http://demo.com/2011/demo-schema">
    <ReportInfo>
        <Name>Demo Report</Name>
        <CreatedBy>Unit Test</CreatedBy>
    </ReportInfo>
</Report>

그리고 아래는 작동해야한다고 생각했지만 작동하지 않는 코드입니다.

XDocument xdoc = XDocument.Load(@"C:\SampleXML.xml");
XmlNamespaceManager xnm = new XmlNamespaceManager(new NameTable()); 
xnm.AddNamespace(String.Empty, "http://demo.com/2011/demo-schema");
Console.WriteLine(xdoc.XPathSelectElement("/Report/ReportInfo/Name", xnm) == null);

누구에게 아이디어가 있습니까? 감사.


1
아래의 다른 답변을 참조하십시오. XPath 1.0 구현이 빈 접두사를 처리 할 수 ​​없기 때문에 작동하지 않습니다
Paul Hatcher

1
다른 사람들이 여기에서 말했듯이 [XmlNamespaceManager]에 네임 스페이스를 추가 할 때 빈 접두사를 사용하지 마십시오. 접미사가 있거나없는 여러 개의 [xmlns] 속성이있는 문서가있는 작은 코드 예제를보고 싶은 경우를 위해이 주석을 추가하는 것입니다. 여기를 참조하십시오 : stackoverflow.com/a/38272604/5838538
Jelgab

답변:


158

XDocument가있는 경우 LINQ-to-XML을 사용하는 것이 더 쉽습니다.

var document = XDocument.Load(fileName);
var name = document.Descendants(XName.Get("Name", @"http://demo.com/2011/demo-schema")).First().Value;

XPath가 필요한 유일한 솔루션이라고 확신하는 경우 :

using System.Xml.XPath;

var document = XDocument.Load(fileName);
var namespaceManager = new XmlNamespaceManager(new NameTable());
namespaceManager.AddNamespace("empty", "http://demo.com/2011/demo-schema");
var name = document.XPathSelectElement("/empty:Report/empty:ReportInfo/empty:Name", namespaceManager).Value;

13
대부분의 경우에 linq가 xpath보다 쉽다고 말하기는 어렵다고 말하고 싶습니다. 예를 들어,이 경우 LINQ에 해당하는 것은 다른 노드 (지금은 없지만 나중에 파일 형식을 변경하여 추가 할 수 있음) 아래에 "Name"노드를 가져 오기 때문에 실제로 동일하지 않습니다. 그러나 귀하의 솔루션은 확실히 올바른 것입니다.
Marco Mp 2013

12
참고 : using System.Xml.XPath; XPathSelectElement는 확장 메서드이기 때문에 매우 중요합니다. ) 그 부분 내가 그랬던 것처럼 않고 무시하지 마십시오
마르크 반 Straten

7
XPath는 부모 자식 관계를 맥락화 할 수 있다는 점에서 여전히 유용합니다. 예 : 당신은 모든 바나나 얻는 대신 / 바나나 / 바나나 / 바나나에 도착하기를 원한다면
세바스찬 패튼

2
여기에서 "비어 있음"은 약간 오해의 소지가 있고 혼란 스럽습니다. XPath, String.Empty (asker가 발견 한대로)를 제외한 모든 것을 사용할 수 있습니다. "demo"가 예제에 더 적합합니다.
Tom Blodget

7

MS가 구현하는 XPath 1.0에는 기본 네임 스페이스에 대한 개념이 없습니다. 그래서 이것을 시도하십시오 :

XDocument xdoc = XDocument.Load(@"C:\SampleXML.xml");
XmlNamespaceManager xnm = new XmlNamespaceManager(new NameTable()); 
xnm.AddNamespace("x", "http://demo.com/2011/demo-schema");
Console.WriteLine(xdoc.XPathSelectElement("/x:Report/x:ReportInfo/x:Name", xnm) == null);

8
귀하의 대답은 XPath 1.0과 달리 XPath 1.0이 기본 네임 스페이스에 대한 "아이디어가 있습니다"라는 것을 의미합니다. 이러한 새로운 XPath 기능에 대해 알지 못합니다 (여기서는 XSLT 또는 XQuery가 아니라 XPath에 대해 이야기하고 있습니다). , 제발, 당신의 대답에 당신이 의미하는 바를 명시 적으로 언급하십시오.
Dimitre Novatchev 2011-06-02

2
그가 여기서 얻는 것은 네임 스페이스를 정의하는 문서가있는 경우 xpath에 정규화 된 요소가 포함되어야한다는 것입니다. 즉, xnm.AddNamespace (string.Empty, " demo.com/2011/demo-schema"를 수행 할 수 없습니다. ); 그리고 xdoc.XPathSelectElement ( "/ Report / ReportInfo / Name", xnm)-결과는 항상 null로 나옵니다
Paul Hatcher

3

네임 스페이스없이 Microsoft 의 예제를 사용할 수 있습니다 .

using System.Xml.Linq;
using System.Xml.XPath;
var e = xdoc.XPathSelectElement("./Report/ReportInfo/Name");     

그것을해야한다


나를 위해 작동하지 않습니다
user1623521
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.