Parsing XML with internal nodes?

I have an XML file as shown below:

<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> 

I need to extract id, name, desc from it and from internal node trade_info I need data/tab, buy_price_rate .

So, initially I thought about this:

  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(); } 

But it does not work, and I'm not sure how to debug it.

From the first error I received, Null Expection, I believe that it could come from node.Descendants("trade_info") , as some clients do not have trade_info at all.

I also believe that there are some of them:

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

As sometimes they do not have items in the list or buy_price_rate.

  • How to check in my request is valid or not to protect it.
  • Is my request approved for what I want?
  • What should i change? Tips?
+4
source share
3 answers

You can also do this ....

  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 } }; 

The main thing is to outline what your packaging class looks like and find out what your default values ​​should be if there is no data for a particular property that you type. (I selected zeros in this example)

+3
source

Your doc value should be of type XElement , then you can choose id as

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

using XName not required, you can just use a string, but it is useful if your xml has namespaces on some elements.

+2
source

Can you change the trade part of your request to:

 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 } 

..

(you need to add using System.Xml.XPath )

+2
source

All Articles