当标签包含 xmlNamespace 时 SelectSingleNode 返回 null

Posted

技术标签:

【中文标题】当标签包含 xmlNamespace 时 SelectSingleNode 返回 null【英文标题】:SelectSingleNode returns null when tag contains xmlNamespace 【发布时间】:2011-05-09 11:00:08 【问题描述】:

我正在将一个字符串加载到一个包含以下结构的 XML 文档中:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">                  
  <ItemGroup>
    <Compile Include="clsWorker.cs" />        
  </ItemGroup>      
</Project>

然后我将所有内容加载到XmlDocument

XmlDocument xmldoc = new XmlDocument();
xmldoc.LoadXml(Xml);

然后出现如下问题:

XmlNode Node = xmldoc.SelectSingleNode("//Compile"); // returns null

当我从根元素 (Project) 中删除 xmlns 属性时,它工作正常。

如何让SelectSingleNode返回相关元素?

【问题讨论】:

【参考方案1】:

您应该在调用SelectSingleNode() 时使用XmlNamespaceManager:

XmlNamespaceManager ns = new XmlNamespaceManager(xmldoc.NameTable);
ns.AddNamespace("msbld", "http://schemas.microsoft.com/developer/msbuild/2003");
XmlNode node = xmldoc.SelectSingleNode("//msbld:Compile", ns);

【讨论】:

这适用于SelectNodes吗? @T.S.,是的。 SelectSingleNode("xpath") 大致相当于SelectNodes("xpath")[0] @Alex,这是任意的,我可以使用任何东西。重要的是在对AddNamespace() 的调用和命名空间前缀中使用相同的名称。 @Alex Jolig,假设你的模式都在标题中指定,你可以做这样的事情来动态添加它们: XmlNamespaceManager ns = new XmlNamespaceManager(xml.NameTable); foreach (xml.DocumentElement.Attributes 中的 XmlAttribute curAttribute) if (curAttribute.Prefix.Equals("xmlns")) ns.AddNamespace(curAttribute.LocalName, curAttribute.Value); 当我们确定源 xml 是一致且同质的时,如何省略所有那些无意义的命名空间,使简单复杂化?【参考方案2】:

取自documentation of SelectSingleNode() on the MSDN:

注意 如果 XPath 表达式不包含前缀,则假定 namespace URI 是空的命名空间。 如果您的 XML 包含默认值 命名空间,您仍然必须将前缀和命名空间 URI 添加到 xml命名空间管理器;否则,您将无法选择节点。 对于 更多信息,请参阅Select Nodes Using XPath Navigation。

紧随其后的示例代码是

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

It'snotasifthiswouldbe“hiddenknowledge”。 ;-)

【讨论】:

【参考方案3】:

这样就不需要指定命名空间了:

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml("your xml");
XmlNode node = xmlDoc.SelectSingleNode("/*[local-name() = 'Compile']");
XmlNode nodeToImport = xmlDoc2.ImportNode(node, true);
xmlDoc2.AppendChild(nodeToImport);

【讨论】:

对我来说有必要使用 //*[local-name 而不是 /*[local-name【参考方案4】:

由于“ItemGroup”可能有多个“Compile”子项,并且您特别想要“Project/ItemGroup”的“Compile”子项,以下将返回所有所需的“Compile”子项,而不返回其他子项:

XmlDocument projectDoc = new XmlDocument();
projectDoc.Load(projectDocPath);
XmlNamespaceManager ns = new XmlNamespaceManager(projectDoc.NameTable);
ns.AddNamespace("msbld", "http://schemas.microsoft.com/developer/msbuild/2003");
XmlNodeList xnList = projectDoc.SelectNodes(@"/msbld:Project/msbld:ItemGroup/msbld:Compile", ns);

请注意,“msbld:”命名空间规范需要位于每个节点级别之前。

【讨论】:

赞成关于多个命名空间规范的警告。

以上是关于当标签包含 xmlNamespace 时 SelectSingleNode 返回 null的主要内容,如果未能解决你的问题,请参考以下文章

使用 WITH XMLNAMESPACES 的 s-s-rS 查询不返回数据集

当元素包含多个类名时如何在硒中复制标签?

锚标签有一半的链接,但是当我点击链接时,它会打开一个包含完整链接的新页面

在标签栏中重新加载当前视图控制器

当存在多个虚拟主机标签时,Apache 2.4.7 重定向不起作用 Ubuntu14.04

当内容包含在流布局中时,如何将单选按钮或复选框及其标签保持在一起