【问题标题】:struggling with XML namespaces (linq)... what am I doing wrong here?与 XML 命名空间(linq)苦苦挣扎……我在这里做错了什么?
【发布时间】:2009-10-18 12:55:02
【问题描述】:

试图解析一些 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>

我在这里遗漏了最后一步?

附言以及为什么 XPath 不能只是更直观的东西,例如:“//SOAP-ENV:Envelope/SOAP-ENV:Body/ReadReplyReq/MMStatus”,而不是必须跳过所有这些疯狂的箍。

【问题讨论】:

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


    【解决方案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 );
    

    可能是你想要的。

    【讨论】:

    • def 只是放入命名空间管理器的一个虚拟前缀,用于标识 Body 的子节点上使用的默认命名空间
    • 我已将您的答案转换为我的 linq 代码,并且确实有效。默认命名空间起到了作用。您怎么能看到您拥有的 url 确实是默认命名空间所需的值?在 xml 中,我只在某处看到该属性: xmlns (xml namespace?) 这是一些始终使用的默认标签吗?
    • Err 我想您可能需要阅读更多有关 XML 命名空间支持的信息 :) 如果您指定 xmlns= 它将将该命名空间 URL 应用于所有不带前缀的子节点。因此,由于 MMStatus 在 ReadReplyRequest 下,它会占用上面的默认设置。
    • 我以前从未遇到过命名空间...从不需要它。我已经很高兴通过大量的谷歌搜索,我得到了 ;^) 我真的认为 xml 有点过头了。感谢上帝的 json ;^)
    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-04
      • 1970-01-01
      • 1970-01-01
      • 2021-04-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多