SelectSingleNode使用XPath为已知良好的xml节点路径返回null

p.c*_*ell 41 c# xml xpath

考虑这个简单的XML文档.这里显示的序列化XML是来自复杂POCO对象的XmlSerializer的结果,该对象的模式我无法控制.

<My_RootNode xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="">
  <id root="2.16.840.1.113883.3.51.1.1.1" extension="someIdentifier" xmlns="urn:hl7-org:v3" /> 
  <creationTime xsi:nil="true" xmlns="urn:hl7-org:v3" />      
</My_RootNode>
Run Code Online (Sandbox Code Playgroud)

目标是在id节点上提取扩展属性的值.在这种情况下,我们使用SelectSingleNode方法,并给出一个XPath表达式:

XmlNode idNode = myXmlDoc.SelectSingleNode("/My_RootNode/id");
//idNode is evaluated to null at this point in the debugger!
string msgID = idNode.Attributes.GetNamedItem("extension").Value;
Run Code Online (Sandbox Code Playgroud)

问题是该SelectSingleNode方法为给定的XPath表达式返回null.

问题:关于此XPath查询的正确性的任何想法,或者为什么此方法调用+ XPath表达式将返回空值?也许命名空间是问题的一部分?

Jon*_*eet 52

我强烈怀疑问题与名称空间有关.尝试摆脱命名空间,你会没事的 - 但显然这对你的实际案例没有帮助,我认为这个文件是固定的.

我不记得如何在XPath表达式中指定命名空间,但我确信这是问题所在.

编辑:好的,我记得现在该怎么做.虽然它不是非常令人愉快 - 你需要XmlNamespaceManager为它创造一个.以下是一些适用于示例文档的示例代码:

using System;
using System.Xml;

public class Test
{
    static void Main()
    {
        XmlDocument doc = new XmlDocument();
        XmlNamespaceManager namespaces = new XmlNamespaceManager(doc.NameTable);
        namespaces.AddNamespace("ns", "urn:hl7-org:v3");
        doc.Load("test.xml");
        XmlNode idNode = doc.SelectSingleNode("/My_RootNode/ns:id", namespaces);
        string msgID = idNode.Attributes["extension"].Value;
        Console.WriteLine(msgID);
    }
}
Run Code Online (Sandbox Code Playgroud)


mrz*_*zli 13

如果要完全忽略名称空间,可以使用:

static void Main(string[] args)
{
    string xml =
        "<My_RootNode xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns=\"\">\n" +
        "    <id root=\"2.16.840.1.113883.3.51.1.1.1\" extension=\"someIdentifier\" xmlns=\"urn:hl7-org:v3\" />\n" +
        "    <creationTime xsi:nil=\"true\" xmlns=\"urn:hl7-org:v3\" />\n" +
        "</My_RootNode>";

    XmlDocument doc = new XmlDocument();
    doc.LoadXml(xml);

    XmlNode idNode = doc.SelectSingleNode("/*[local-name()='My_RootNode']/*[local-name()='id']");
}
Run Code Online (Sandbox Code Playgroud)


小智 9

这应该适用于你的情况而不删除命名空间:

XmlNode idNode = myXmlDoc.GetElementsByTagName("id")[0];
Run Code Online (Sandbox Code Playgroud)


Joh*_*ers 8

对不起,您忘记了命名空间.你需要:

XmlNamespaceManager ns = new XmlNamespaceManager(myXmlDoc.NameTable);
ns.AddNamespace("hl7","urn:hl7-org:v3");
XmlNode idNode = myXmlDoc.SelectSingleNode("/My_RootNode/hl7:id", ns);
Run Code Online (Sandbox Code Playgroud)

实际上,无论是在此处还是在Web服务中,从XPath操作或依赖于XPath的任何操作返回null通常都表明XML命名空间存在问题.

  • 我相信John几乎是完全正确的,因为"id"元素的全名是"urn:h17-org:v3"和"id".您正在使用XPATH搜索""和"id",因此找不到任何内容.但是,要实际工作,您需要将ns实例作为SelectSingleNode的第二个参数传递. (2认同)