3

我有代码来获取根元素的节点:

xmlNodes = rootElement.SelectNodes("DefinitionName");

它不返回存在的节点。在调试器中,我可以展开 rootElement 以找到 DefinitionName。显然问题在于该文件定义了一个命名空间(参见下面的 XML)。MSDN说我必须做这样的事情才能让节点返回:

注意:这与我的代码无关。这是来自 MSDN 的示例:

XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("ab", "http://www.lucernepublishing.com");
XmlNodeList nodelist = doc.SelectNodes("//ab:book", nsmgr);

我有两个问题:

  1. 为什么命名空间很重要?如果我想要一个节点,并且它存在,就给我。
  2. 我的应用程序处理许多 XML 文件。我应该如何指定命名空间(nsmgr.AddNamespace())?我需要先解析文件才能得到它吗?

我情不自禁地觉得我正在采取漫长而充满焦虑的方式来做这件事。

这是 XML:

    <?xml version="1.0" encoding="utf-8"?>
    <SessionStateInfo xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
    z:Id="1" z:Type="Company.Apps.MoreHere.Session.SessionStateInfo"
    z:Assembly="assembly info here"
    xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/"
    xmlns="http://schemas.datacontract.org/2004/07/MoreHere.Session">
      <CoaterNumber>25</CoaterNumber>
      <DefinitionName z:Id="2">Two Line</DefinitionName>
      <EnableManualMode>true</EnableManualMode>
4

3 回答 3

4
<SessionStateInfo ....
    xmlns="http://schemas.datacontract.org/2004/07/MoreHere.Session">

表示此元素及其所有后代都在http://schemas.datacontract.org/2004/07/MoreHere.Session命名空间中。由于 XPath 中的无前缀名称始终引用非命名空间中的元素,因此您需要将此 URI 绑定到一个前缀并在 XPath 中使用该前缀,即使文档中没有使用任何前缀。

XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("mhs", "http://schemas.datacontract.org/2004/07/MoreHere.Session");
xmlNodes = rootElement.SelectNodes("mhs:DefinitionName", nsmgr);

如果您知道要查找的元素将始终具有相同的本地名称,但可能有也可能没有命名空间(或可能有不同的命名空间),那么您可以使用 XPath 技巧,例如

rootElement.SelectNodes("*[local-name() = 'DefinitionName']");
于 2013-03-28T16:11:02.947 回答
2

这很重要,因为如果附加了命名空间,那么“DefinitionName”是不够的。想象一下,你得到了一个人的名单,所有人的名字都是约翰:

  • 约翰·史密斯
  • 约翰·琼斯
  • 约翰墨菲

例如,您所做的相当于要求“John”而不是“John Smith”。

于 2013-03-28T16:13:03.373 回答
1

这不完全是问题的答案,但它可能是使用的替代解决方案XDocument

using System;
using System.Dynamic;
using System.Xml.Linq;
using Microsoft.CSharp.RuntimeBinder;
using System.Linq;

namespace ConsoleApplication8
{
    class Program
    {
        static void Main(string[] args)
        {
            XDocument document = XDocument.Load("SessionStateInfo.xml");
            XNamespace nameSpace = document.Root.GetDefaultNamespace();
            XElement node = document.Descendants(nameSpace + "DefinitionName").FirstOrDefault();   

            if (node != null)
            {
                Console.WriteLine("Cool! XDocument rocks! value: {0}", node.Value);
            }
            else
            {
                Console.WriteLine("Spoot! Didn't find it!");
            }
        }      
    }       
}

无论是否指定了默认命名空间,这似乎都有效。

于 2013-03-28T20:35:41.223 回答