Reputation: 19528
I have a XML file like the 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 from it id, name, desc
and from the inner node trade_info I need data/tab, buy_price_rate
.
So initially I was thinking of 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 seem to work and im not sure on how to debug it.
From the first error I got, Null Expection I belive it may be coming from the node.Descendants("trade_info")
as some clients have no trade_info at all.
I also belive there is some comming from:
Id = n.Element("tab_list").Element("data").Element("tab").Value,
Buy = n.Element("buy_price_rate").Value
As sometimes they dont have items on the list or buy_price_rate.
Upvotes: 4
Views: 648
Reputation: 18815
you could 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 map out what your wrapping class looks like and work out what your defaults should be in case there is no data for the specific property you will map. (I chose nulls in this example)
Upvotes: 3
Reputation: 4232
Can you change the trade
part of your query 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'll need to add using System.Xml.XPath
)
Upvotes: 2
Reputation: 25
Your value doc should of type XElement
then you can select id
like
var query = from el in doc.Descendants(XName.Get("id"))
select el.Value;
using XName
is not necessary you can just use a string, but is useful if your xml has namespaces on some of the elements.
Upvotes: 2