Null returned when selecting a node in XML document

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-23 02:28:41

问题


New to XML. I have a 3rd party webservice that supplies an XML document that I have to update the element values and pass back. The core issue issue is I get an NullReferenceException error when calling the node.RemoveAll() method in the code below. I'm calling the RemoveAll() method because each element has the xsi:nil attribute when it is supplied to me, and if I don't remove it before updating the element value, the XML won't validate by the webservice.

The XML document supplied by the 3rd party webservice is as follows:

<?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>

Other solutions I've seen have used the XmlNamespaceManager, but I haven't been able to make it work. This xml document has a namespace specified for the TaskData element, and a different namespace for the RequestInfo element. I tried specifying the XmlNamespaceManager variable for each namespace, but got the same results....hovering over the nsmgr variable while in break mode reveals that the "children could not be evaluated" and that the DefaultNamespace property is an empty string.

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

回答1:


The problem is with this statement:

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

what you need to do is

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

"s:Requestor" means give me the node underneath the current node name s:Requestor

"//s:Requestor" means give me all nodes in the document named s:Requestor

if you want to ignore the namespace you could do

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



回答2:


There are two errors in your code. One is the XPath used for selecting the node (as Greg pointed out). The second one is the name space. I may be wrong, but as I interpret the XML document the TaskData element has the following namespace declaration:

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

...which sets up the namespace for elements without prefixes.

But then the RequestInfo tag has this namespace declaration:

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

So within the RequestInfo tag, there is another namespace for tags without prefixes. In your code you use the first of these two namespaces to match a tag that resides in the second, which will not work out. There are two ways to solve it. One is to simply change the namespace in your code:

XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("s", "http://schema.sample.com/application/1/Types");
XmlNode node = doc.SelectSingleNode("//s:Requestor", nsmgr);

The second one is to define both namespaces, and use an XPath expression that points out the full path to the tag:

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);

Both these cases lead to the same result; node is not null.




回答3:


I'm not sure whether I have understood your task correctly. But if you have to just remove the xsi:nil="true" part, why don't you load it as a string and invoke a

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

Of course that's not the cleanest solution, but I'm not yet comfortable with the XML handling API of C#, so I'd have to consult the MSDN to get accustomed. Maybe this solves already your issue.




回答4:


You should be able to opt out of any namespace calls in your selectelement call, i prefer to loop through my document anyway.. but that's just me.



来源:https://stackoverflow.com/questions/972584/null-returned-when-selecting-a-node-in-xml-document

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!