可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm calling a WebService exposed by Oracle that accepts an input of an ItemID and returns to me the corresponding Item Number. I want to grab the Item Number that has been returned out of the XML contained in the response.
The XML looks like this:
<env:Envelope
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ns0="http://dev1/MyWebService1.wsdl">
<env:Header>
<wsse:Security
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
env:mustUnderstand="1"/>
</env:Header>
<env:Body>
<ns0:getItemNbrByItemIdResponseElement>
<ns0:result>1010603</ns0:result>
</ns0:getItemNbrByItemIdResponseElement>
</env:Body>
</env:Envelope>
I'm interested in grabbing only the <ns0:result>1010603</ns0:result>
particularly only the 1010603.
I haven't done a lot of work parsing XML using C# and I'm playing around with a few different methods so far. What is the recommended way to do this?
I'm on VS2008 (so XPath is available etc.)
回答1:
I'd personally use LINQ to XML, because I find that easier to deal with than XPath, particularly when namespaces are involved. You'd do something like:
XNamespace ns0 = "http://dev1/MyWebService1.wsdl";
String result = doc.Descendants(ns0 + "result").First().Value;
Note that doc
here is expected to be an XDocument
, not an XmlDocument
. (My guess is that this is why it wasn't showing up for you.)
回答2:
fwiw you can cheat the namespace issue with an xpath like this: //*[local-name()='result']
回答3:
If you don't want to go for Linq you could use XPathDocument to retrieve the value:
XPathDocument xmldoc = new XPathDocument(@"C:\tmp\sample.xml");
XPathNavigator nav = xmldoc.CreateNavigator();
XmlNamespaceManager nsMgr = new XmlNamespaceManager(nav.NameTable);
nsMgr.AddNamespace("ns0", "http://dev1/MyWebService1.wsdl");
XPathNavigator result = nav.SelectSingleNode("//ns0:result", nsMgr);
System.Diagnostics.Debug.WriteLine(result.Value);
XPathDocument has a lower memory footprint and is most likely faster in your scenario than XmlDocument. XmlDocument builds up a complete object model of your XML document in memory whereas XPathDocument does not do that.
回答4:
Off the top of my head, the following should work:
XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = true;
XmlNamespaceManager mgr = GetNamespace(doc);
doc.LoadXml(xmltext);
XmlNode nd = doc.DocumentElement.SelectSingleNode("//ns0:result", mgr);
The namespace code looks like this:
private XmlNamespaceManager GetNamespace(XmlDocument document)
{
XmlNamespaceManager mgr = new XmlNamespaceManager(document.NameTable);
mgr.AddNamespace("ns0", "http://dev1/MyWebService1.wsdl");
return mgr;
}
You need to use the namespace manager because the XML document has namespaces associated with it, and XPath uses this in query resolution.
回答5:
To solve this, I used Jon Skeet's answer. Here's the code that I had to implement to make this work (for anyone else's future benefit).
XmlDocument xmlDoc = new XmlDocument();
XNamespace ns0 = "http://dev1/MyWebService1.wsdl";
xmlDoc.Load(request.GetResponse().GetResponseStream());
XDocument xDoc = XDocument.Load(new XmlNodeReader(xmlDoc));
String result = xDoc.Descendants(ns0 + "result").First().Value;
This of course assumes I'm getting my response back from an HttpWebRequest named request.
回答6:
There are very good and complete answers to this question.
I'd add just out of curiosity, that an extremely simple XPath expression does the job in this particular case:
normalize-space(/)
This is easily done in C# using something like the two lines below:
XPathNavigator navigator = document.CreateNavigator();
string res = (string)navigator.Evaluate("normalize-space(/)");
With the good optimization of the .NET XPath engine, its evaluation may even be efficient.