【问题标题】:Finding element attribute with XDocument使用 XDocument 查找元素属性
【发布时间】:2013-05-15 11:26:24
【问题描述】:

我正在尝试从以下 XML 结构(Windows Phone 应用内购买的收据)中获取 PurchaseDate:

<Receipt Version="1.0" CertificateId="..." xmlns="http://schemas.microsoft.com/windows/2012/store/receipt">
  <ProductReceipt PurchasePrice="$0" PurchaseDate="2013-05-20T19:27:09.755Z" Id="..." AppId="..." ProductId="Unlock" ProductType="Consumable" PublisherUserId="..." PublisherDeviceId="..." MicrosoftProductId="..." />
  <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
      <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
      <SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
      <Reference URI="">
        <Transforms>
          <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
        </Transforms>
        <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
        <DigestValue>...</DigestValue>
      </Reference>
    </SignedInfo>
    <SignatureValue>...</SignatureValue>
  </Signature>
</Receipt>

我的代码如下:

XDocument doc = XDocument.Parse(receiptXml);

string date = doc.Root.Element("ProductReceipt").Attribute("PurchaseData").Value;

这不断引发访问错误,因为doc.Root.Element("ProductReceipt") 为空。为什么 XDocument 没有得到 ProductReceipt 元素?

【问题讨论】:

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


    【解决方案1】:

    只需将命名空间添加到您的 LINQ to XML 查询。因为您在根节点xmlns="http://schemas.microsoft.com/windows/2012/store/receipt" 有默认命名空间声明,所以您还需要在查询中指定它。

    接下来的代码展示了一个例子:

    XDocument doc = XDocument.Parse(receiptXml);
    
    XNamespace xmlns = "http://schemas.microsoft.com/windows/2012/store/receipt";
    
    string date = doc.Root
                     .Element(xmlns + "ProductReceipt")
                     .Attribute("PurchaseDate")
                     .Value;
    
    Console.WriteLine(date);
    

    打印:

    2013-05-20T19:27:09.755Z
    

    还有一种与命名空间无关的方法:

    string date = doc.Root
                     .Elements()
                     .First(node => node.Name.LocalName == "ProductReceipt")
                     .Attribute("PurchaseDate")
                     .Value;
    

    【讨论】:

    • 请注意,如果您希望日期为 DateTime,您可以将其简化为:var date = (DateTime) doc.Root.Element(xmlns + "ProductReceipt").Attribute("PurchaseDate");
    • @MatthewWatson 感谢您的关注。尽管 OP 已明确将字符串指定为日期的数据类型。如果他愿意,可以更改。
    • 伟大而简洁的答案!非常感谢! @MatthewWatson 的笔记也很有帮助,谢谢!
    猜你喜欢
    • 1970-01-01
    • 2012-01-17
    • 2020-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-05
    相关资源
    最近更新 更多