【问题标题】:Parse certain node of XML file解析 XML 文件的某个节点
【发布时间】:2019-11-24 00:22:35
【问题描述】:

我有这个 XML 文件(为简洁起见被截断):

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<feed xml:base="http://data.treasury.gov/Feed.svc/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
  <title type="text">DailyTreasuryYieldCurveRateData</title>
  <id>http://data.treasury.gov/feed.svc/DailyTreasuryYieldCurveRateData</id>
  <updated>2019-11-23T23:48:22Z</updated>
  <link rel="self" title="DailyTreasuryYieldCurveRateData" href="DailyTreasuryYieldCurveRateData" />
  <entry>
    <id>http://data.treasury.gov/Feed.svc/DailyTreasuryYieldCurveRateData(7258)</id>
    <title type="text"></title>
    <updated>2019-11-23T23:48:22Z</updated>
    <author>
      <name />
    </author>
    <link rel="edit" title="DailyTreasuryYieldCurveRateDatum" href="DailyTreasuryYieldCurveRateData(7258)" />
    <category term="TreasuryDataWarehouseModel.DailyTreasuryYieldCurveRateDatum" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
    <content type="application/xml">
      <m:properties>
        <d:Id m:type="Edm.Int32">7258</d:Id>
        <d:NEW_DATE m:type="Edm.DateTime">2019-01-02T00:00:00</d:NEW_DATE>
        <d:BC_1MONTH m:type="Edm.Double">2.4</d:BC_1MONTH>
        <d:BC_2MONTH m:type="Edm.Double">2.4</d:BC_2MONTH>
        <d:BC_3MONTH m:type="Edm.Double">2.42</d:BC_3MONTH>
        <d:BC_6MONTH m:type="Edm.Double">2.51</d:BC_6MONTH>
        <d:BC_1YEAR m:type="Edm.Double">2.6</d:BC_1YEAR>
        <d:BC_2YEAR m:type="Edm.Double">2.5</d:BC_2YEAR>
        <d:BC_3YEAR m:type="Edm.Double">2.47</d:BC_3YEAR>
        <d:BC_5YEAR m:type="Edm.Double">2.49</d:BC_5YEAR>
        <d:BC_7YEAR m:type="Edm.Double">2.56</d:BC_7YEAR>
        <d:BC_10YEAR m:type="Edm.Double">2.66</d:BC_10YEAR>
        <d:BC_20YEAR m:type="Edm.Double">2.83</d:BC_20YEAR>
        <d:BC_30YEAR m:type="Edm.Double">2.97</d:BC_30YEAR>
        <d:BC_30YEARDISPLAY m:type="Edm.Double">2.97</d:BC_30YEARDISPLAY>
      </m:properties>
    </content>
  </entry>
  <entry>
    <id>http://data.treasury.gov/Feed.svc/DailyTreasuryYieldCurveRateData(7259)</id>
    <title type="text"></title>
    <updated>2019-11-23T23:48:22Z</updated>
    <author>
      <name />
    </author>
    <link rel="edit" title="DailyTreasuryYieldCurveRateDatum" href="DailyTreasuryYieldCurveRateData(7259)" />
    <category term="TreasuryDataWarehouseModel.DailyTreasuryYieldCurveRateDatum" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
    <content type="application/xml">
      <m:properties>
        <d:Id m:type="Edm.Int32">7259</d:Id>
        <d:NEW_DATE m:type="Edm.DateTime">2019-01-03T00:00:00</d:NEW_DATE>
        <d:BC_1MONTH m:type="Edm.Double">2.42</d:BC_1MONTH>
        <d:BC_2MONTH m:type="Edm.Double">2.42</d:BC_2MONTH>
        <d:BC_3MONTH m:type="Edm.Double">2.41</d:BC_3MONTH>
        <d:BC_6MONTH m:type="Edm.Double">2.47</d:BC_6MONTH>
        <d:BC_1YEAR m:type="Edm.Double">2.5</d:BC_1YEAR>
        <d:BC_2YEAR m:type="Edm.Double">2.39</d:BC_2YEAR>
        <d:BC_3YEAR m:type="Edm.Double">2.35</d:BC_3YEAR>
        <d:BC_5YEAR m:type="Edm.Double">2.37</d:BC_5YEAR>
        <d:BC_7YEAR m:type="Edm.Double">2.44</d:BC_7YEAR>
        <d:BC_10YEAR m:type="Edm.Double">2.56</d:BC_10YEAR>
        <d:BC_20YEAR m:type="Edm.Double">2.75</d:BC_20YEAR>
        <d:BC_30YEAR m:type="Edm.Double">2.92</d:BC_30YEAR>
        <d:BC_30YEARDISPLAY m:type="Edm.Double">2.92</d:BC_30YEARDISPLAY>
      </m:properties>
    </content>
  </entry>
  <entry>
    <id>http://data.treasury.gov/Feed.svc/DailyTreasuryYieldCurveRateData(7260)</id>
    <title type="text"></title>
    <updated>2019-11-23T23:48:22Z</updated>
    <author>
      <name />
    </author>
    <link rel="edit" title="DailyTreasuryYieldCurveRateDatum" href="DailyTreasuryYieldCurveRateData(7260)" />
    <category term="TreasuryDataWarehouseModel.DailyTreasuryYieldCurveRateDatum" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
    <content type="application/xml">
      <m:properties>
        <d:Id m:type="Edm.Int32">7260</d:Id>
        <d:NEW_DATE m:type="Edm.DateTime">2019-01-04T00:00:00</d:NEW_DATE>
        <d:BC_1MONTH m:type="Edm.Double">2.4</d:BC_1MONTH>
        <d:BC_2MONTH m:type="Edm.Double">2.42</d:BC_2MONTH>
        <d:BC_3MONTH m:type="Edm.Double">2.42</d:BC_3MONTH>
        <d:BC_6MONTH m:type="Edm.Double">2.51</d:BC_6MONTH>
        <d:BC_1YEAR m:type="Edm.Double">2.57</d:BC_1YEAR>
        <d:BC_2YEAR m:type="Edm.Double">2.5</d:BC_2YEAR>
        <d:BC_3YEAR m:type="Edm.Double">2.47</d:BC_3YEAR>
        <d:BC_5YEAR m:type="Edm.Double">2.49</d:BC_5YEAR>
        <d:BC_7YEAR m:type="Edm.Double">2.56</d:BC_7YEAR>
        <d:BC_10YEAR m:type="Edm.Double">2.67</d:BC_10YEAR>
        <d:BC_20YEAR m:type="Edm.Double">2.83</d:BC_20YEAR>
        <d:BC_30YEAR m:type="Edm.Double">2.98</d:BC_30YEAR>
        <d:BC_30YEARDISPLAY m:type="Edm.Double">2.98</d:BC_30YEARDISPLAY>
      </m:properties>
    </content>
  </entry>
  <entry>
    <id>http://data.treasury.gov/Feed.svc/DailyTreasuryYieldCurveRateData(7261)</id>
    <title type="text"></title>
    <updated>2019-11-23T23:48:22Z</updated>
    <author>
      <name />
    </author>
    <link rel="edit" title="DailyTreasuryYieldCurveRateDatum" href="DailyTreasuryYieldCurveRateData(7261)" />
    <category term="TreasuryDataWarehouseModel.DailyTreasuryYieldCurveRateDatum" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
    <content type="application/xml">
      <m:properties>
        <d:Id m:type="Edm.Int32">7261</d:Id>
        <d:NEW_DATE m:type="Edm.DateTime">2019-01-07T00:00:00</d:NEW_DATE>
        <d:BC_1MONTH m:type="Edm.Double">2.42</d:BC_1MONTH>
        <d:BC_2MONTH m:type="Edm.Double">2.42</d:BC_2MONTH>
        <d:BC_3MONTH m:type="Edm.Double">2.45</d:BC_3MONTH>
        <d:BC_6MONTH m:type="Edm.Double">2.54</d:BC_6MONTH>
        <d:BC_1YEAR m:type="Edm.Double">2.58</d:BC_1YEAR>
        <d:BC_2YEAR m:type="Edm.Double">2.53</d:BC_2YEAR>
        <d:BC_3YEAR m:type="Edm.Double">2.51</d:BC_3YEAR>
        <d:BC_5YEAR m:type="Edm.Double">2.53</d:BC_5YEAR>
        <d:BC_7YEAR m:type="Edm.Double">2.6</d:BC_7YEAR>
        <d:BC_10YEAR m:type="Edm.Double">2.7</d:BC_10YEAR>
        <d:BC_20YEAR m:type="Edm.Double">2.86</d:BC_20YEAR>
        <d:BC_30YEAR m:type="Edm.Double">2.99</d:BC_30YEAR>
        <d:BC_30YEARDISPLAY m:type="Edm.Double">2.99</d:BC_30YEARDISPLAY>
      </m:properties>
    </content>
  </entry>
  ...

我需要获取 NEW_DATEBC_x_YEAR 数据。我编写了这个程序,让我看到m:properties 部分,但我不知道如何提取该部分中的值?

using System;
using System.Xml;

class Program
{
    static void Main()
    {
        // Create an XML reader for this file.
        using (XmlReader reader = XmlReader.Create(@"C:\Users\idf\Downloads\IRs\2019.xml"))
        {
            while (reader.Read())
            {
                // Only detect start elements.
                if (reader.IsStartElement())
                {
                    // Get element name and switch on it.
                    switch (reader.Name)
                    {
                        case "m:properties":
                            // Detect this element.
                            Console.WriteLine("Start <m:properties> element."); 
                            break;
                        default:
                            Console.WriteLine(reader.Name);
                            break;
                    }
                }
            }
        }
    }
}

【问题讨论】:

    标签: c# xml-parsing


    【解决方案1】:

    您可以为此目的使用 Linq to Xml。例如,

    var xDoc = XDocument.Parse(xml);
    XNamespace rootNs = xDoc.Root.GetDefaultNamespace();
    XNamespace dataServiceNs = "http://schemas.microsoft.com/ado/2007/08/dataservices";
    var keysToSearch = new []{"NEW_DATE","BC_1YEAR","BC_2YEAR","BC_3YEAR","BC_5YEAR","BC_7YEAR","BC_10YEAR","BC_20YEAR","BC_30YEAR"};
    foreach(var entry in xDoc.Descendants(rootNs+"entry"))
    {
        Console.WriteLine($"Entry Id: {entry.Element(rootNs+"id").Value}");
        foreach(var key in keysToSearch)
        {
            Console.WriteLine($"{key}:{entry.Descendants(dataServiceNs + key).First().Value}");
        }
    }
    

    如果您不想根据entry 对它们进行分组,那么您甚至可以这样做

    foreach(var key in keysToSearch)
    {
        foreach(var item in xDoc.Descendants(dataServiceNs + key))
        {
            Console.WriteLine($"{key}:{item.Value}");
        }
    }
    

    【讨论】:

    • 请注意XDocument 将首先解析整个文件,而XmlReader 一次读取一个令牌。对于大型 XML 文件,这可能是一个重大问题。
    • 严重性代码描述项目文件行抑制状态错误 CS1061 'IEnumerable' 不包含对 'First' 的定义,并且没有可访问的扩展方法 'First' 接受类型为 'IEnumerable'(您是否缺少 using 指令或程序集引用?)
    • 当使用 XDocument.Parse(xml) 方法时,我得到 System.Xml.XmlException HResult=0x80131940 Message=Data in the root level is invalid。第 1 行,位置 1。Source=System.Xml
    • 我在 IE 中加载了 xml 文档,我没有收到任何错误。奇怪...
    • @Ivan 希望您在 Xml 末尾关闭了提要标签...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-31
    相关资源
    最近更新 更多