1

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

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

4 回答 4

2

问题出在这句话上:

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

你需要做的是

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

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

"//s:Requestor" 表示给我文档中名为 s:Requestor 的所有节点

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

doc.SelectSingleNode("//*[local-name()='Requestor']")
于 2009-06-09T21:39:28.530 回答
1

您的代码中有两个错误。一种是用于选择节点的 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

于 2009-06-09T22:05:50.397 回答
0

我不确定我是否正确理解了您的任务。但是,如果您只需要删除 xsi:nil="true" 部分,为什么不将它作为字符串加载并调用

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

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

于 2009-06-09T21:29:42.250 回答
0

您应该能够在您的 selectelement 调用中选择退出任何命名空间调用,无论如何我更喜欢循环浏览我的文档.. 但这只是我。

于 2009-06-12T05:00:20.573 回答