在XML文档中选择节点时返回Null

在XML文档中选择节点时返回Null,xml,vb.net,selectsinglenode,Xml,Vb.net,Selectsinglenode,XML新手。我有一个第三方Web服务,它提供一个XML文档,我必须更新元素值并传回。核心问题是在下面的代码中调用node.RemoveAll()方法时出现NullReferenceException错误。我之所以调用RemoveAll()方法,是因为每个元素在提供给我时都有xsi:nil属性,如果我在更新元素值之前不删除它,那么Web服务将不会验证XML 第三方Web服务提供的XML文档如下所示: <?xml version="1.0" encoding="utf-16"?> <

XML新手。我有一个第三方Web服务,它提供一个XML文档,我必须更新元素值并传回。核心问题是在下面的代码中调用node.RemoveAll()方法时出现NullReferenceException错误。我之所以调用RemoveAll()方法,是因为每个元素在提供给我时都有xsi:nil属性,如果我在更新元素值之前不删除它,那么Web服务将不会验证XML

第三方Web服务提供的XML文档如下所示:

<?xml version="1.0" encoding="utf-16"?>
<TaskData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schema.sample.com/application/1/520800B">
  <Global>
    <RequestInfo xmlns="http://schema.sample.com/application/1/Types">
      <Requestor xsi:nil="true" />
      <Date_init xsi:nil="true" />
      <Shipto xsi:nil="true" />
      <Customer xsi:nil="true" />
      <Contact xsi:nil="true" />
      <Requestor_Email xsi:nil="true" />      
    </RequestInfo>    
   </Global>
  </TaskData>

我不确定我是否正确理解了你的任务。但是如果必须删除xsi:nil=“true”部分,为什么不将其作为字符串加载并调用

string.replace("xsi:nil=\"true\"", "")

当然,这不是最干净的解决方案,但我还不熟悉C#的XML处理API,因此我必须参考MSDN才能习惯。也许这已经解决了你的问题。

问题在于这句话:

doc.SelectSingleNode("s:Requestor", nsmgr)
你需要做的是

doc.SelectSingleNode("//s:Requestor",nsmgr)
“s:Requestor”表示给我当前节点名s:Requestor下的节点

“//s:Requestor”表示将名为s:Requestor的文档中的所有节点都给我

如果要忽略名称空间,可以这样做

doc.SelectSingleNode("//*[local-name()='Requestor']")

代码中有两个错误。一个是用于选择节点的XPath(正如Greg指出的)。第二个是名称空间。我可能错了,但在解释XML文档时,
TaskData
元素具有以下名称空间声明:

xmlns="http://schema.sample.com/application/1/520800B"
xmlns="http://schema.sample.com/application/1/Types"
…它为没有前缀的元素设置名称空间

但是,
RequestInfo
标记有以下名称空间声明:

xmlns="http://schema.sample.com/application/1/520800B"
xmlns="http://schema.sample.com/application/1/Types"
因此,在
RequestInfo
标记中,有另一个不带前缀的标记名称空间。在您的代码中,您使用这两个名称空间中的第一个来匹配驻留在第二个名称空间中的标记,这是行不通的。有两种方法可以解决这个问题。一种是简单地更改代码中的名称空间:

XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("s", "http://schema.sample.com/application/1/Types");
XmlNode node = doc.SelectSingleNode("//s:Requestor", nsmgr);
第二种方法是定义两个名称空间,并使用XPath表达式指出标记的完整路径:

XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("r", "http://schema.sample.com/application/1/520800B");
nsmgr.AddNamespace("s", "http://schema.sample.com/application/1/Types");
XmlNode node = doc.SelectSingleNode(@"/r:TaskData/r:Global/s:RequestInfo/s:Requestor", nsmgr);

这两种情况导致相同的结果
node
不是
null

您应该能够选择退出selectelement调用中的任何命名空间调用,但我还是希望遍历我的文档。。但那只是我。

谢谢,朱丽。我遇到的问题是没有设置变量“node”,当调用RemoveAll()方法时,它抛出异常。您能看到我的XPath语法有什么问题吗?这样“node”变量就被设置为正确的元素了?太棒了!忽略您建议的NS的选项是有效的,我更喜欢它,因为我无法控制第三方Web服务分配的名称空间。我尝试了“//s:Requestor”,但没有成功。Fredrik,我喜欢能够指定元素的完整路径。由于这是我的第一篇文章,我还没有足够的声誉来投票给你的答案,但它非常有帮助,谢谢你!