架构问题会阻止SelectNodes()查找节点吗?

时间:2017-04-04 15:46:39

标签: c# xml xpath schema

我有一些非常基本的XML:

<ReconnectResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://platform.intuit.com/api/v1">    
    <ErrorMessage/>    
    <ErrorCode>0</ErrorCode>    
    <ServerTime>2012-01-04T19:21:21.0782072Z</ServerTime>    
    <OAuthToken>redacted</OAuthToken>    
    <OAuthTokenSecret>redacted</OAuthTokenSecret>
</ReconnectResponse>

简单,对吧?

因此,当我想获得ErrorCode的值时,我对XPath的体验告诉我尝试/ReconnectResponse/ErrorCode/text()。这适用于配备XML Tools插件的Notepad ++,所以让我们在C#中尝试:

var xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlString);
var namespaceMan = new XmlNamespaceManager(xmlDoc.NameTable);
Console.WriteLine(xmlDoc.SelectSingleNode(@"/ReconnectResponse/ErrorCode", namespaceMan).InnerText);

我得到一个例外:

  

对象引用未设置为对象的实例。

这有点像找到指定节点的问题。考虑到XML的简单性,我正在努力找出出错的地方。

一时兴起,我将XML填入XMLQuire。这会为每种元素类型提供XSD架构错误,如下所示:

  

无法找到元素“http://platform.intuit.com/api/v1:ReconnectResponse”的架构信息。

所以,我的问题是架构错误是否会导致SelectSingleNode()错过我的节点?次要问题:我该如何解决?

1 个答案:

答案 0 :(得分:1)

您忽略了元素的命名空间,在本例中为http://platform.intuit.com/api/v1。这由根元素中的xmlns=".."属性定义,所有子元素都继承此属性。

您需要使用前缀

将此命名空间添加到命名空间管理器
namespaceMan.AddNamespace("api", "http://platform.intuit.com/api/v1");

在查询中使用此前缀:

xmlDoc.SelectSingleNode(@"/api:ReconnectResponse/api:ErrorCode", namespaceMan).InnerText;

另外,LINQ to XML比XmlDocument更清晰,并提供比XPath更好的查询语言。此代码将为您提供整数错误代码:

var doc = XDocument.Parse(xmlString);

XNamespace api = "http://platform.intuit.com/api/v1";

var errorCode = (int) doc.Descendants(api + "ErrorCode").Single();