XDocument ile XPath nasıl kullanılır?


109

Benzer bir soru var, ancak benim durumumda çözüm işe yaramadı: XDocument, XPath ve ad alanlarındaki tuhaflık

İşte çalıştığım 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>

Ve aşağıda çalışması gerektiğini düşündüğüm kod var ama işe yaramadı ...

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);

Herhangi bir fikri olan var mı? Teşekkürler.


1
Aşağıdaki diğer yanıta bakın, XPath 1.0 uygulaması boş bir önekle baş edemediği için çalışmıyor
Paul Hatcher

1
Burada da belirtildiği gibi, [XmlNamespaceManager] 'a bir Ad Alanı eklerken boş bir önek kullanmayın. Bu yorumu, sonek içeren ve içermeyen birkaç [xmlns] özniteliği olan bir belgeye sahip küçük bir kod örneği görmek istemesi durumunda ekliyorum. Buraya bakın: stackoverflow.com/a/38272604/5838538
Jelgab

Yanıtlar:


158

XDocument'e sahipseniz, LINQ-to-XML'i kullanmak daha kolaydır:

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

XPath'in ihtiyacınız olan tek çözüm olduğundan eminseniz:

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
Çoğu durumda linq'in xpath'den daha kolay olduğunu söylemenin zor olduğunu söyleyebilirim. Örneğin, bu durumda LINQ eşdeğeri, diğer düğümler altında "Ad" düğümlerini de alacağı için gerçekten eşdeğer değildir (bunlar şu anda yoktur, ancak dosyanın biçimine daha sonra yapılan değişikliklerle eklenebilir). Ancak sizin çözümünüz kesinlikle doğru olanıdır.
Marco Mp

12
NOT: System.Xml.XPath kullanarak; XPathSelectElement bir uzantı yöntemi olduğu için oldukça önemlidir. Yaptığım gibi yapmayın ve o kısmı görmezden
gelin

7
XPath, ebeveyn çocuk ilişkilerinizi bağlamsallaştırmanıza izin verdiği için hala yararlıdır. Örneğin, her Muz almak yerine / Muz / Muz / Muz'a gitmek istediyseniz
Sebastian Patten

2
"boş" burada biraz yanıltıcı ve kafa karıştırıcıdır. XPath, String.Empty (soruyu soranın keşfettiği gibi) dışında herhangi bir şey kullanabilirsiniz. "demo" örneğe daha uygun olacaktır.
Tom Blodget

7

MS'in uyguladığı XPath 1.0, varsayılan bir ad alanı fikrine sahip değildir. Öyleyse şunu dene:

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);

9
Cevabınız, XPath 1.0'ın "* aksine, XPath 2.0'ın varsayılan bir ad alanı" fikrine "sahip olduğunu ima ediyor. Bu tür yeni XPath özelliğinin farkında değilim (burada XSLT veya XQuery'den değil, XPath'den bahsediyoruz). Bu nedenle, yapabilir misin? , lütfen, cevabınızda neyi ima ettiğinizi
açıkça belirtin

2
Ne o burada, elde ettiğini bir ad tanımlayan bir belge varsa lütfen xpath nitelikli unsurları içermelidir olduğunu düşünüyorum, yani xnm.AddNamespace (string.Empty, "yapamaz demo.com/2011/demo-schema" ); ve sonra xdoc.XPathSelectElement ("/ Report / ReportInfo / Name", xnm) - sonuç her zaman boş çıkıyor
Paul Hatcher

3

Microsoft'tan örnek kullanabilirsiniz - sizin için ad alanı olmadan:

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

yapmalı


benim için çalışmıyor
user1623521
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.