XML SelectNode()不返回任何内容.为什么名称空间很重要
本文关键字:空间 为什么 SelectNode 任何内 返回 XML | 更新日期: 2023-09-27 18:06:33
我有代码来获取根元素的节点:
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);
我有两个问题:
- 为什么名称空间很重要?如果我想要一个节点,并且它存在,就把它给我
- 我的应用程序处理许多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>
<SessionStateInfo ....
xmlns="http://schemas.datacontract.org/2004/07/MoreHere.Session">
意味着该元素及其所有子元素都在http://schemas.datacontract.org/2004/07/MoreHere.Session
命名空间中。由于XPath中未固定的名称总是引用no命名空间中的元素,因此您需要将此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']");
这很重要,因为如果附加了命名空间,那么"DefinitionName"是不够的。想象一下,你收到了一份名单,所有人的名字都是John:
- 约翰·史密斯
- 约翰·琼斯
- 约翰·墨菲
你所做的相当于要求"约翰",而不是"约翰·史密斯"。
这不是问题的确切答案,但它可能是使用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!");
}
}
}
}
无论是否指定了默认命名空间,这似乎都有效。