2013-02-05 16 views
7

Ich versuche, die XElement.XPathSelectElements() - Überladung aufzurufen, die ein IXmlNamespaceResolver-Objekt erfordert. Kann jemand mir zeigen, wie man einen IXmlNamespaceResolver erhält (oder macht)? Ich habe eine Liste der Namensräume IWie bekomme ich einen IXmlNamespaceResolver?

Antwort

4

Sie in meiner Abfrage verwenden möchten, können eine XmlNamespaceManager verwenden, die diese Schnittstelle

Verwenden Sie den Konstruktor implementiert, die eine XmlNameTable nimmt, in sie eine Instanz von System.Xml.NameTable über new NameTable() vorbei. Sie können dann AddNamespace Funktion aufrufen Namespace hinzuzufügen:

new XmlNamespaceManager(new NameTable())
var nsMgr = new XmlNamespaceManager(new NameTable()); 
nsMgr.AddNamespace("ex", "urn:example.org"); 
nsMgr.AddNamespace("t", "urn:test.org"); 
doc.XPathSelectElements("/ex:path/ex:to/t:element", nsMgr); 
+0

D'oh! -Vielen Dank. Es ist eine Schande, dass es keine einfache Möglichkeit gibt, dies in der Dokumentation zu sehen. – Andy

+10

Es gibt keinen parameterlosen Konstruktor. Siehe [this] (http://msdn.microsoft.com/en-us/library/system.xml.xmlnamespacemanager.xmlnamespacemanager (v = vs.110) .aspx) Artikel. – Bernard

+0

Siehe diese Antwort auf eine andere Frage. – MonkeyWrench

10

Verwendung.

Zum Beispiel, wenn Sie ein XML-Dokument, das Namespaces wie

var xDoc = XDocument.Parse(@"<m:Student xmlns:m='http://www.ludlowcloud.com/Math'> 
    <m:Grade>98</m:Grade> 
    <m:Grade>96</m:Grade> 
</m:Student>"); 

verwendet dann können Sie die Grade Knoten erhalten, indem

var namespaceResolver = new XmlNamespaceManager(new NameTable()); 
namespaceResolver.AddNamespace("math", "http://www.ludlowcloud.com/Math"); 
var grades = xDoc.XPathSelectElements("//math:Student/math:Grade", namespaceResolver); 
4

tun fand ich diesen Beitrag bei der Suche über die Verwendung die Überladung von [XPathSelectElements()], um eine SOAP-Antwort zu verarbeiten, so werde ich meine Antwort posten, falls sie für andere nützlich ist, die ein Dokument mit mehreren Namespace-Definitionen haben. In meinem Fall habe ich ein Dokument wie folgt aus:

var theDocumentXDoc = XDocument.Parse(theDocumentContent); 

Um die [XmlNamespaceManager] zu erstellen, verwende ich:

<?xml version="1.0" encoding="utf-8"?> 
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <soap:Body> 
    <queryResponse xmlns="http://SomeUrl.com/SomeSection"> 
     <response> 
     <theOperationId>105</theOperationId> 
     <theGeneraltheDetailsCode>0</theGeneraltheDetailsCode> 
     <theDetails> 
      <aDetail> 
      <aDetailId>111</aDetailId> 
      <theValue>Some Value</theValue> 
      <theDescription>Some description</theDescription> 
      </aDetail> 
      <aDetail> 
      <aDetailId>222</aDetailId> 
      <theValue>Another Value</theValue> 
      <theDescription>Another description</theDescription> 
      </aDetail> 
      <aDetail> 
      <aDetailId>333</aDetailId> 
      <theValue>And another Value</theValue> 
      <theDescription>And another description</theDescription> 
      </aDetail> 
     </theDetails> 
     </response> 
    </queryResponse> 
    </soap:Body> 
</soap:Envelope> 

die [XDocument] So erstellen

var theNamespaceIndicator = new XmlNamespaceManager(new NameTable()); 
theNamespaceIndicator.AddNamespace("theSoapNS", "http://www.w3.org/2003/05/soap-envelope"); 
theNamespaceIndicator.AddNamespace("noSuffNS" , "http://SomeUrl.com/SomeSection"); 

Die Namen Ich verwende für die Präfixe ("theSoapNS" und "noSuffNS") beliebig. Verwenden Sie einen Namen, der für einen lesbaren Code geeignet ist.

die [Umschlag] Element auszuwählen, die ich benutze:

var theEnvelope = theDocumentXDoc.XPathSelectElement("//theSoapNS:Envelope", theNamespaceIndicator); 

die [queryResponse] Element auszuwählen:

var theQueryResponse = theDocumentXDoc.XPathSelectElement("//theSoapNS:Envelope/theSoapNS:Body/noSuffNS:queryResponse", theNamespaceIndicator); 

alle Details wählen in [theDetails]:

var theDetails = theDocumentXDoc.XPathSelectElement("//theSoapNS:Envelope/theSoapNS:Body/noSuffNS:queryResponse/noSuffNS:response/noSuffNS:theDetails", theNamespaceIndicator); 

Hier ist ein Beispielprogramm (C# 6) mit den folgenden Auswahlen:

//The usings you need: 
using System; 
using System.Linq; 
using System.Xml; 
using System.Xml.Linq; 
using System.Xml.XPath; 

namespace ProcessXmlCons 
{ 
    class Inicial 
    { 
     static void Main(string[] args) 
     { 
      new Inicial().Tests(); 
     } 

     private void Tests() 
     { 
      Test01(); 
     } 

     private void Test01() 
     { 
      var theDocumentContent = 
       @"<?xml version=""1.0"" encoding=""utf-8""?> 
        <soap:Envelope xmlns:soap=""http://www.w3.org/2003/05/soap-envelope"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema""> 
         <soap:Body> 
         <queryResponse xmlns=""http://SomeUrl.com/SomeSection""> 
          <response> 
           <theOperationId>105</theOperationId> 
           <theGeneraltheDetailsCode>0</theGeneraltheDetailsCode> 
           <theDetails> 
            <aDetail> 
             <aDetailId>111</aDetailId> 
             <theValue>Some Value</theValue> 
             <theDescription>Some description</theDescription> 
            </aDetail> 
            <aDetail> 
             <aDetailId>222</aDetailId> 
             <theValue>Another Value</theValue> 
             <theDescription>Another description</theDescription> 
            </aDetail> 
            <aDetail> 
             <aDetailId>333</aDetailId> 
             <theValue>And another Value</theValue> 
             <theDescription>And another description</theDescription> 
            </aDetail> 
           </theDetails> 
          </response> 
         </queryResponse> 
         </soap:Body> 
        </soap:Envelope> 
        "; 

      var theDocumentXDoc = XDocument.Parse(theDocumentContent); 
      var theNamespaceIndicator = new XmlNamespaceManager(new NameTable()); 
      theNamespaceIndicator.AddNamespace("theSoapNS", "http://www.w3.org/2003/05/soap-envelope"); 
      theNamespaceIndicator.AddNamespace("noSuffNS", "http://SomeUrl.com/SomeSection"); 

      var theEnvelope = theDocumentXDoc.XPathSelectElement("//theSoapNS:Envelope", theNamespaceIndicator); 
      Console.WriteLine($"The envelope: {theEnvelope?.ToString()} "); 

      var theEnvelopeNotFound = theDocumentXDoc.XPathSelectElement("//Envelope", theNamespaceIndicator); 
      Console.WriteLine("".PadRight(120, '_')); //Visual divider 
      Console.WriteLine($"The other envelope: \r\n {theEnvelopeNotFound?.ToString()} "); 

      var theQueryResponse = theDocumentXDoc.XPathSelectElement("//theSoapNS:Envelope/theSoapNS:Body/noSuffNS:queryResponse", theNamespaceIndicator); 
      Console.WriteLine("".PadRight(120, '_')); //Visual divider 
      Console.WriteLine($"The query response: \r\n {theQueryResponse?.ToString()} "); 

      var theDetails = theDocumentXDoc.XPathSelectElement("//theSoapNS:Envelope/theSoapNS:Body/noSuffNS:queryResponse/noSuffNS:response/noSuffNS:theDetails", theNamespaceIndicator); 
      Console.WriteLine("".PadRight(120, '_')); //Visual divider 
      Console.WriteLine($"The details: \r\n {theDetails?.ToString()} "); 
      Console.WriteLine("".PadRight(120, '_')); //Visual divider 

      foreach (var currentDetail in theDetails.Descendants().Where(elementToFilter => elementToFilter.Name.LocalName != "aDetail")) 
      { 
       Console.WriteLine($"{currentDetail.Name.LocalName}: {currentDetail.Value}"); 
      } 

      //Not optimal. Just to show XPath select within another selection: 
      Console.WriteLine("".PadRight(120, '_')); //Visual divider 
      Console.WriteLine("Values only:"); 
      foreach (var currentDetail in theDetails.Descendants()) 
      { 
       var onlyTheValueElement = currentDetail.XPathSelectElement("noSuffNS:theValue", theNamespaceIndicator); 
       if (onlyTheValueElement != null) 
       { 
        Console.WriteLine($"--> {onlyTheValueElement.Value}"); 
       } 
      } 
     } 

    } //class Inicial 
} //namespace ProcessXmlCons 
+0

Danke! Genau dafür bin ich hergekommen. –