How do I get an IXmlNamespaceResolver
Asked Answered
M

3

14

I'm trying to call the XElement.XPathSelectElements() overload that requires an IXmlNamespaceResolver object. Can anyone show me how to get (or make) an IXmlNamespaceResolver? I have a list of the namespaces I want to use in my query

Muzhik answered 5/2, 2013 at 16:54 Comment(0)
P
8

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);
Procuration answered 5/2, 2013 at 17:51 Comment(4)
D'oh! -Thanks. It's a shame there isn't an easy way to see this from the documentationMuzhik
There is no parameterless constructor. See this article.Seashore
See this answer to another question.Briard
Yes you can use an XmlNamespaceManager but the point is you shouldn't have to. The XDocument stuff lets you just say XNamespace ns = new XNamespace(...); new XElement(ns + "nodeName"...); - no namespace resolver required. Having to then add a resolver is going to duplicate your namespace definitions.Maidenhead
G
11

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);
Guzman answered 6/2, 2016 at 1:40 Comment(0)
P
8

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);
Procuration answered 5/2, 2013 at 17:51 Comment(4)
D'oh! -Thanks. It's a shame there isn't an easy way to see this from the documentationMuzhik
There is no parameterless constructor. See this article.Seashore
See this answer to another question.Briard
Yes you can use an XmlNamespaceManager but the point is you shouldn't have to. The XDocument stuff lets you just say XNamespace ns = new XNamespace(...); new XElement(ns + "nodeName"...); - no namespace resolver required. Having to then add a resolver is going to duplicate your namespace definitions.Maidenhead
B
4

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
Bornite answered 8/7, 2016 at 17:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.