How do I get an IXmlNamespaceResolver

前端 未结 3 646
一向
一向 2021-01-11 12:57

I\'m trying to call the XElement.XPathSelectElements() overload that requires an IXmlNamespaceResolver object. Can anyone show me how to get (or make) an IXmlNamespaceResolv

相关标签:
3条回答
  • 2021-01-11 13:38

    Use new XmlNamespaceManager(new NameTable()).

    For example, if you have an XML document that uses namespaces like

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

    then you can get the Grade nodes by doing

    var namespaceResolver = new XmlNamespaceManager(new NameTable());
    namespaceResolver.AddNamespace("math", "http://www.ludlowcloud.com/Math");
    var grades = xDoc.XPathSelectElements("//math:Student/math:Grade", namespaceResolver);
    
    0 讨论(0)
  • 2021-01-11 13:38

    I found this post while searching on how to use the overload of [XPathSelectElements()] to process a SOAP response so, I will post my answer in case it is usefull for others who have a document with several namespace definitions. In my case I have a document like this:

    <?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>
    

    To create the [XDocument]:

    var theDocumentXDoc = XDocument.Parse( theDocumentContent );
    

    To create the [XmlNamespaceManager], I use:

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

    The names I use for the prefixes ( "theSoapNS" and "noSuffNS" ) are arbitrary. Use a name that is convenient for a readable code.

    To select the [Envelope] element, I use:

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

    To select the [queryResponse] element:

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

    To select all details in [theDetails]:

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

    Here is an example program (C#6) using the selections:

    //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 讨论(0)
  • 2021-01-11 13:41

    You can use an XmlNamespaceManager that implements that interface

    Use the constructor which takes an XmlNameTable, passing into it an instance of System.Xml.NameTable via new NameTable(). You can then call AddNamespace function to add namespaces:

    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 讨论(0)
提交回复
热议问题