13

我正在尝试调用需要 IXmlNamespaceResolver 对象的 XElement.XPathSelectElements() 重载。谁能告诉我如何获取(或制作)IXmlNamespaceResolver?我有一个要在查询中使用的命名空间列表

4

3 回答 3

11

使用new XmlNamespaceManager(new NameTable()).

例如,如果您有一个使用如下命名空间的 XML 文档

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

然后你可以Grade通过做得到节点

var namespaceResolver = new XmlNamespaceManager(new NameTable());
namespaceResolver.AddNamespace("math", "http://www.ludlowcloud.com/Math");
var grades = xDoc.XPathSelectElements("//math:Student/math:Grade", namespaceResolver);
于 2016-02-06T01:40:23.610 回答
7

您可以使用实现该接口的XmlNamespaceManager

使用接受 a 的构造函数,将viaXmlNameTable的实例传递给它。然后您可以调用函数来添加命名空间:System.Xml.NameTablenew NameTable()AddNamespace

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);
于 2013-02-05T17:51:02.350 回答
4

我在搜索如何使用 [XPathSelectElements()] 的重载来处理 SOAP 响应时发现了这篇文章,因此,我将发布我的答案,以防它对拥有多个命名空间定义的文档的其他人有用。就我而言,我有这样的文件:

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

要创建 [XDocument]:

var theDocumentXDoc = XDocument.Parse( theDocumentContent );

要创建 [XmlNamespaceManager],我使用:

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

我用于前缀的名称(“theSoapNS”和“noSuffNS”)是任意的。使用便于阅读代码的名称。

要选择 [Envelope] 元素,我使用:

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

要选择 [queryResponse] 元素:

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

要选择 [theDetails] 中的所有详细信息:

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

这是一个使用选择的示例程序 (C#6):

//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
于 2016-07-08T17:44:09.960 回答