【问题标题】:Simplest way to get XML nodes with namespace?使用命名空间获取 XML 节点的最简单方法?
【发布时间】:2018-04-18 12:30:24
【问题描述】:

我有以下 XML:

<?xml version="1.0" encoding="UTF-8"?>
<createTransactionResponse xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd" 
                          xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <messages>
      <resultCode>Ok</resultCode>
      <message>
         <code>I00001</code>
         <text>Successful.</text>
      </message>
   </messages>
   <transactionResponse>
      <responseCode>1</responseCode>
      <authCode>25C10X</authCode>
      <messages>
         <message>
            <code>1</code>
            <description>This transaction has been approved.</description>
         </message>
      </messages>
  </transactionResponse>
</createTransactionResponse>

获得“成功”值的最简单方法是什么?来自createTransactionResponse-&gt;messages-&gt;message-&gt;text?

这是我的代码:

XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
var nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("anet", "AnetApi/xml/v1/schema/AnetApiSchema.xsd");
var myNodes = doc.SelectNodes("//anet:messages", nsmgr);

myNodes 返回 2 个节点。 node[0]的innerxml是:

<resultCode xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd">Ok</resultCode><message xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd">
   <code>I00001</code>
   <text>Successful.</text>
</message>

node[1]的innerxml是:

<message xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd">
   <code>1</code>
   <description>This transaction has been approved.</description>
</message>

我的问题是我不能再深入了。

//anet:messages/message 什么也没产生。 //anet:createTransactionResponse/messages 什么也没产生。

我只是想获取特定的元素值,例如“I00001”和“25C10X”。

我做错了什么?

【问题讨论】:

  • 这个可靠的问题被低估了。对于初学者来说,默认命名空间适用于后代元素并不明显。另外,OP 根据需要提供了minimal reproducible example。我正在投票并修改编辑时间戳;希望一些严厉的反对票会看到并扭转。
  • @kjhughes 同意了。这是对问题的清晰简洁的陈述。
  • 我已经习惯了。有些人无缘无故地跑来跑去投票。可能是在浴室隔间刮脏话的人。 SO 可以通过非匿名投票或至少在投票时要求理由来轻松制止这种情况。

标签: c# xml xpath linq-to-xml


【解决方案1】:

命名空间绑定是继承的,所以这里的子元素与其父元素在同一个命名空间中。

您需要在查询中添加缺少的命名空间前缀:

//anet:messages/anet:message/anet:text

也就是说,我通常更喜欢 LINQ 而非 XPath:

XNamespace ns = "AnetApi/xml/v1/schema/AnetApiSchema.xsd";

var root = XElement.Parse(xml);

var text = (string) root.Elements(ns + "messages")
    .Descendants(ns + "text")
    .Single();

请参阅this fiddle 以获得工作演示。

【讨论】:

    【解决方案2】:

    您还可以使用 LocalName 属性来避免使用命名空间:

    XDocument root = XDocument.Parse(xml);
    
    string text = root.Descendants()
        .First(node => node.Name.LocalName == "messages").Elements()
        .First(node => node.Name.LocalName == "message").Elements()
        .First(node => node.Name.LocalName == "text").Value;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-11
      • 1970-01-01
      • 2013-06-19
      • 2014-06-27
      • 2023-03-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多