struggling with XML namespaces (linq)... what am I doing wrong here?
Trying to parse some XML but apparently this is too much for a lazy sunday afternoon,
this is my code: (I Tried the XPathDocument and XmlDocument approach too but this also failed miserably)
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(postData);
XDocument xDoc = XDocument.Load(new XmlNodeReader(xmlDoc));
XNamespace soapEnv = "http://schemas.xmlsoap.org/soap/envelope/";
XElement xEnv = xDoc.Descendants(soapEnv + "Envelope").First();
XElement xBody = xEnv.Descendants(soapEnv + "Body").First();
XElement xReadReply = xBody.Descendants("ReadReplyReq").First();
The last line fails with the exception: no elements in this collection however if I change this last line into:
XElement xReadReply = xBody.Descendants().First();
it returns the first node which in fact is the "ReadReplyReq" node.
Having finally gotten these Namespaces working, it now fails on the first node without a namepace... ooh bitter irony ;^)
This is the XML I'm trying to parse:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<TransactionID xmlns="http://www.3gpp.org/ftp/Specs/archive/23_series/23.140/schema/REL-5-MM7-1-2" SOAP-ENV:actor="" SOAP-ENV:mustUnderstand="1">12345678</TransactionID>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ReadReplyReq xmlns="http://www.3gpp.org/ftp/Specs/archive/23_series/23.140/schema/REL-5-MM7-1-2">
<MMStatus>Read</MMStatus>
<TimeStamp>2007-12-13T14:05:27+01:00</TimeStamp>
<MessageID>54321</MessageID>
<Sender>
<ShortCode>+12345</ShortCode>
</Sender>
<Recipient>
<Number>+12345</Number>
</Recipient>
<StatusText>Message has been read</StatusText>
<MM7Version>5.3.0</MM7Version>
</ReadReplyReq>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
what last step am I missing here?
p.s. and why can't the XPath not just be something more intuitive like: "//SOAP-EN开发者_JAVA技巧V:Envelope/SOAP-ENV:Body/ReadReplyReq/MMStatus", instead of all these crazy hoops one has to jump through.
I am guessing what you want is to add a namespace manager so you can XPath select on prefixed nodes?
If so then something like:
var doc = new XmlDocument();
doc.LoadXml( postData );
var ns = new XmlNamespaceManager( doc.NameTable );
ns.AddNamespace( "SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/" );
ns.AddNamespace( "def", "http://www.3gpp.org/ftp/Specs/archive/23_series/23.140/schema/REL-5-MM7-1-2" );
XmlNode list = doc.SelectSingleNode( "//SOAP-ENV:Envelope/SOAP-ENV:Body/def:ReadReplyReq/def:MMStatus", ns );
Is probably what you want.
You don't need XPath you just need a namespace for the xReadReply element. Declare the namespace just like you did for the soap elements and use it when searching for that element.
XNamespace transNS = "http://www.3gpp.org/ftp/Specs/archive/23_series/23.140/schema/REL-5-MM7-1-2";
XElement xReadReply = xBody.Descendants( transNS + "ReadReplyReq" ).First();
精彩评论