Here's the json string I have.
{ "?xml" : { "@version" : "1.0", "@encoding" : "UTF-8" }, "DataFeed" : { "@FeedName" : "issuerDetails", "SecurityDetails" : { "Security" : { "SecurityID" : { "@idValue" : "AAPL-NSDQ", "@fiscalYearEnd" : "2016-12-31T00:00:00.00" }, "FinancialModels" : { "FinancialModel" : [{ "@id" : "780", "@name" : "Estimates - Energy", "@clientCode" : "A", "Values" : [{ "@name" : "EBITDA", "@clientCode" : "EBITDA", "@currency" : "C$", "Value" : [{ "@year" : "2014", "#text" : "555.64" }, { "@year" : "2015", "#text" : "-538.986" }, { "@year" : "2016", "#text" : "554.447" }, { "@year" : "2017", "#text" : "551.091" }, { "@year" : "2018", "#text" : "0" } ] }, { "@name" : "EPS", "@clientCode" : "EPS", "@currency" : "C$", "Value" : [{ "@year" : "2014", "#text" : "0" }, { "@year" : "2015", "#text" : "-1.667" }, { "@year" : "2016", "#text" : "-1.212" }, { "@year" : "2017", "#text" : "0.202" }, { "@year" : "2018", "#text" : "0" } ] }, { "@name" : "CFPS", "@clientCode" : "CFPS", "@currency" : "C$", "Value" : [{ "@year" : "2014", "#text" : "3.196" }, { "@year" : "2015", "#text" : "-0.207" }, { "@year" : "2016", "#text" : "0.599" }, { "@year" : "2017", "#text" : "2.408" }, { "@year" : "2018", "#text" : "0" } ] } ] } ] } } } } }
How can I select #text data for EPS for the years 2015, 2016, 2017? Here is the query that I still have:
JObject jsonFeed = JObject.Parse(jsonText); var query = from security in jsonFeed.SelectTokens("DataFeed.SecurityDetails.Security") .SelectMany(i => i.ObjectsOrSelf()) let finModels = security.SelectTokens("FinancialModels.FinancialModel") .SelectMany(s => s.ObjectsOrSelf()).FirstOrDefault() where finModels != null select new { FinModelClientCode = (string)finModels.SelectToken("Values[1] .@clientCode "), FinModelYear2015 = (string)finModels.SelectToken("Values[1].Value[1] .@year "), FinModelValue2015 = (string)finModels.SelectToken("Values[1].Value[1].#text"), FinModelYear2016 = (string)finModels.SelectToken("Values[1].Value[2] .@year "), FinModelValue2016 = (string)finModels.SelectToken("Values[1].Value[2].#text"), FinModelYear2017 = (string)finModels.SelectToken("Values[1].Value[3] .@year "), FinModelValue2017 = (string)finModels.SelectToken("Values[1].Value[3].#text"), };
Here are the jsonExtensions that I use:
public static class JsonExtensions { public static IEnumerable<JToken> DescendantsAndSelf(this JToken node) { if (node == null) return Enumerable.Empty<JToken>(); var container = node as JContainer; if (container != null) return container.DescendantsAndSelf(); else return new[] { node }; } public static IEnumerable<JObject> ObjectsOrSelf(this JToken root) { if (root is JObject) yield return (JObject)root; else if (root is JContainer) foreach (var item in ((JContainer)root).Children()) foreach (var child in item.ObjectsOrSelf()) yield return child; else yield break; } public static IEnumerable<JToken> SingleOrMultiple(this JToken source) { IEnumerable<JToken> arr = source as JArray; return arr ?? new[] { source }; } }
The problem is that EPS will not always be in one position for the next company? Therefore, I want the query to search for the EPS client code and return values ββfor the years mentioned above, hopefully using the DRY method. Could you help me finish my inquiry?
NOTE: I actually load the XML string by converting it to JSON and then parsing it.
XmlDocument doc = new XmlDocument(); doc.LoadXml(xmlString); jsonText = Newtonsoft.Json.JsonConvert.SerializeXmlNode(doc); JObject jsonFeed = JObject.Parse(jsonText);