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

时间:2009-06-09 21:24:01

标签: xml vb.net selectsinglenode

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

第三方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>

我见过的其他解决方案已使用XmlNamespaceManager,但我无法使其工作。此xml文档具有为TaskData元素指定的命名空间,以及RequestInfo元素的不同命名空间。我尝试为每个命名空间指定XmlNamespaceManager变量,但得到相同的结果....在中断模式下将鼠标悬停在nsmgr变量上会显示“无法计算子项”,并且DefaultNamespace属性为空字符串。

Public Sub testxml()

    Dim doc As New XmlDocument
    doc.Load("c:\temp\sample.xml")

    Dim nsmgr As XmlNamespaceManager = New XmlNamespaceManager(doc.NameTable)
    nsmgr.AddNamespace("s", "http://schema.sample.com/application/1/520800B")

    Dim node As XmlNode = doc.SelectSingleNode("s:Requestor", nsmgr)
    node.RemoveAll()
    node.InnerText = "Your Name Goes Here"

    doc.Save("c:\temp\sample.xml")

End Sub

4 个答案:

答案 0 :(得分:2)

问题在于这句话:

doc.SelectSingleNode("s:Requestor", nsmgr)

你需要做的是

doc.SelectSingleNode("//s:Requestor",nsmgr)

“s:Requestor”表示给我当前节点名称下的节点:Requestor

“// s:Requestor”表示给我名为s:Requestor

的文档中的所有节点

如果你想忽略你可以做的命名空间

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

答案 1 :(得分:0)

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

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

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

答案 2 :(得分:0)

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

xmlns="http://schema.sample.com/application/1/520800B"

...为没有前缀的元素设置名称空间。

但是RequestInfo标签有这个命名空间声明:

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

答案 3 :(得分:0)

你应该能够在你的选择调用中选择退出任何命名空间调用,我更喜欢循环遍历我的文档..但这只是我。