【问题标题】:Load selective XML data into Dataset using C#使用 C# 将选择性 XML 数据加载到数据集中
【发布时间】:2011-07-06 17:45:23
【问题描述】:

感谢一些关于如何在 XML 文件上使用 XPath 来仅提取一些数据并将其加载到数据集中的指针。

ds.ReadXml(fsReadXml);

会将整个 xml 加载到数据集中,但我的要求是仅将特定节点和值加载到数据集。

示例 xml 数据:

<data cobdate="5 Jul 2011" DBStatus="">
  <view>BOTH</view>
  <show_acctnbr>true</show_acctnbr>
  <summary>
    <headings sum="Summary" real_per="Realized this period" real_trd="Profit/loss in trading currency" real_select="Profit/loss in selected currency" short_term="Short Term Profit/Loss" long_term="Long Term Profit/Loss" />
    <account number="A123456" curr_code="USD" curr_desc="US Dollars" tradecurrvalue="123,123.00" selectcurrvalue="123,123.00" managed="NO" />
    <account number="P123456" curr_code="USD" curr_desc="US Dollars" tradecurrvalue="0.00" selectcurrvalue="0.00" managed="NO" />
  </summary>
  <detail>
    <headings dateaq="Date acquired" datesld="Date sold" desc="Description" sec_nbr="Security number " qty="Quantity" cost="Cost basis" />
    <account number="A123456" currency="US Dollars">
      <item datesold="29 Apr 11" sec_nbr="1234" description="SOME VALUE(USD)" quantity="8,000" proceeds="123,123.0" />
      <item datesold="29 Apr 11" sec_nbr="4567" description="SOME VALUE(USD)" quantity="9,000" proceeds="123,123.0" />
    </account>
    <account number="P123456" currency="US Dollars">
      <item datesold="29 Apr 11" sec_nbr="1234" description="SOME VALUE(USD)" quantity="8,000" proceeds="123,123.0" />
      <item datesold="29 Apr 11" sec_nbr="4567" description="SOME VALUE(USD)" quantity="9,000" proceeds="123,123.00" />
    </account>
  </detail>
</data>

在这个示例数据中,我只需要从 &lt;summary&gt; 节点加载账户,如果可能的话,只需要加载 number、tradecurrvalue 和 selectcurrvalue 属性。我使用 C# 和 3.5。

【问题讨论】:

  • 是否需要 XPath 和 DataSet?
  • XPath 不是必需的。但要求是将 XML 放入数据集中。我刚刚意识到我的 xml 数据不在文件中,而是作为字符串传递给我。我想我可以使用XDocument.Parse(string)
  • 是的,加载或解析无关紧要。
  • 好问题,+1。请参阅我对单行 XPath 表达式解决方案的回答 :)
  • @Dimitre 这不是 1 行,最多 1 个语句 (:。为了比较,添加骨架代码以将结果加载到其他内容中。

标签: c# xml linq xpath


【解决方案1】:

使用 XDocument:

var doc = XDocument.Load(fileName);
var lst = doc
       .Descendants("summary")   // don't care where summary is
       .Elements("account ")     // direct child of <summary>
       .Select(x => new 
       {
          number = x.Attribute("number").Value,
          ...
       });

foreach(var account in lst) 
{
  .... // add to DataSet
}

【讨论】:

  • 非常简洁的解决方案 Henk。 Linq 减少代码行的方式总是让我感到惊讶。现在,我可以使用这段代码。谢谢!
  • @Henk 如果我们知道只有一个摘要节点,如果我们使用doc.Element("summary") 而不是doc.Decendants("summary"),我们会得到什么好处,特别是如果文档非常大,摘要后面有很多细节节点?
  • #Conrad,您可能会通过指定确切的路径获得一些好处,但会失去灵活性。但主要成本是加载和解析,您已经支付了这些费用。
【解决方案2】:

也可以使用XmlNodeListXmlNode,比其他的轻量级

  foreach (XmlNode node in nodes)
            {
                dt.Rows.Add(node["Name"].InnerText.ToString(),
                            node["NoOfDay"].InnerText.ToString(),
                            node["dateColumn"].InnerText.ToString()
                           );
            }

Reference Link

【讨论】:

    【解决方案3】:

    在您的代码中评估此 XPath 表达式

    /*/summary/account/@*
                [contains('|number|tradecurrvalue|selectcurrvalue|',
                          concat('|',name(),'|')
                          )
                ]
    

    这将选择名为"number""tradecurrvalue""selectcurrvalue" 的任何属性(属于任何summary 元素的子元素的任何account 元素的子元素,该元素是XML 文档中顶部元素的子元素)

    扩大您想要选择的可能属性名称列表非常容易——只需将它们包含在以竖线分隔的名称列表中即可。

    【讨论】:

      猜你喜欢
      • 2011-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-09
      • 2010-11-12
      • 1970-01-01
      相关资源
      最近更新 更多