用内部节点解析XML?

时间:2010-11-24 05:37:21

标签: c# parsing linq-to-xml

我有一个如下所示的XML文件:

 <clients>
  <client>
    <id>YYYY</id>
    <name>XXXX</name>
    <desc>ZZZZ</desc>
    <trade_info>
      <tab_list>
       <data>
         <tab>book 123</tab>
       </data>
       <data>
         <tab>cook 321</tab>
       </data>
      </tab_list>
      <buy_price_rate>200</buy_price_rate>
    </trade_info>
  </client>
 </clients>

我需要从中提取id, name, desc,并从内部节点trade_info中提取data/tab, buy_price_rate

所以最初我在想这个:

    var query = from node in doc.Descendants("client")
                select new
                {
                    client = new
                    {
                        Id = node.Element("id").Value,
                        Name = node.Element("name").Value,
                        Desc = node.Element("desc").Value
                    },

                    trade = from n in node.Descendants("trade_info")
                               select new
                               {
                                   Id = n.Element("tab_list").Element("data").Element("tab").Value,
                                   Buy = n.Element("buy_price_rate").Value
                               }
                };

        foreach (var item in query)
        {
            writeXML.WriteStartElement("tradelist_template");
            writeXML.WriteAttributeString("client_id", item.client.Id);
            foreach (var trade in item.trade)
            {
                writeXML.WriteStartElement("tradelist");
                writeXML.WriteAttributeString("item_id", trade.Id);
                writeXML.WriteEndElement();
            }
            writeXML.WriteEndElement();
        }

但它似乎不起作用,我不确定如何调试它。

从我收到的第一个错误中,我相信它可能来自node.Descendants("trade_info"),因为有些客户根本没有trade_info。

我也相信有一些来自:

Id = n.Element("tab_list").Element("data").Element("tab").Value,
Buy = n.Element("buy_price_rate").Value

有时他们没有列表中的项目或buy_price_rate。

  • 如何在查询中查看
  • 是否为无效或无法保护它
  • 我的查询是否符合我的要求?
  • 我应该改变什么?建议?

3 个答案:

答案 0 :(得分:3)

你也可以这样做....

  var list = from item in doc.Descendants("client")
             let tradeinfoelement = item.Element("trade_info")
             select new
             {
               Client = new
               {
                 Id = (string)item.Element("id"),
                 Name = (string)item.Element("name"),
                 Desc = (string)item.Element("desc")
               },
               TradeInfo = new
               {
                 BuyPrice = tradeinfoelement.Element("buy_price_rate")  != null ? (int?)tradeinfoelement.Element("buy_price_rate") : null,
                 Tabs = tradeinfoelement.Descendants("tab") != null ? tradeinfoelement.Descendants("tab").Select(t => (string)t).ToList() : null
               }
             };

主要是绘制你的包装类的外观,并找出你的默认值应该是什么,以防你将映射的特定属性没有数据。 (我在这个例子中选择了空值)

答案 1 :(得分:2)

您的价值文档应为XElement类型,然后您可以选择id喜欢

var query = from el in doc.Descendants(XName.Get("id"))
 select el.Value;

使用XName不是必需的,您可以只使用字符串,但如果您的xml在某些元素上具有名称空间,则非常有用。

答案 2 :(得分:2)

您可以将查询的trade部分更改为:

trade = from n in node.Descendants("trade_info")
  select new
  {
    Id = (n.XPathSelectElement("tab_list/data/tab") == null) ? null : n.XPathSelectElement("tab_list/data/tab").Value,
    Buy = (n.Element("buy_price_rate") == null) ? null : n.Element("buy_price_rate").Value
  }

...

(您需要添加using System.Xml.XPath