当标签包含 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 查询不返回数据集
锚标签有一半的链接,但是当我点击链接时,它会打开一个包含完整链接的新页面