挣扎着XML命名空间(linq)......我在这里做错了什么?

时间:2009-10-18 12:55:03

标签: c# .net xml soap linq-to-xml

尝试解析一些XML,但显然这对于​​一个懒惰的周日下午来说太过分了,

这是我的代码:(我也尝试了XPathDocument和XmlDocument方法,但这也失败了)

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

最后一行失败,异常:此集合中没有元素 但是,如果我将最后一行更改为:

 XElement xReadReply = xBody.Descendants().First();

它返回第一个节点,实际上是“ReadReplyReq”节点。

终于让这些命名空间工作了,它现在在没有名称空间的第一个节点上失败了......讽刺的是讽刺的; ^)

这是我正在尝试解析的XML:

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

我在这里失踪的最后一步是什么?

P.S。为什么XPath不能只是更直观的东西:“// SOAP-ENV:Envelope / SOAP-ENV:Body / ReadReplyReq / MMStatus”,而不是所有这些疯狂的箍都必须跳过。

2 个答案:

答案 0 :(得分:1)

我猜你想要的是添加命名空间管理器,以便XPath在前缀节点上选择?

如果是这样的话,那就是:

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

可能是你想要的。

答案 1 :(得分:1)

您不需要XPath,只需要xReadReply元素的命名空间。像对soap元素一样声明命名空间,并在搜索该元素时使用它。

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