{"id":57,"date":"2011-10-14T14:38:00","date_gmt":"2011-10-14T14:38:00","guid":{"rendered":"\/lisa\/post\/2011\/10\/14\/Actual-Factual-JSON-data-in-SSRS.aspx"},"modified":"2011-10-14T14:38:00","modified_gmt":"2011-10-14T14:38:00","slug":"actual-factual-json-data-in-ssrs","status":"publish","type":"post","link":"https:\/\/spacefold.com\/lisa\/2011\/10\/14\/actual-factual-json-data-in-ssrs\/","title":{"rendered":"Actual Factual JSON data in SSRS"},"content":{"rendered":"<p>One of the fun things about my job is its constant exposure to collaborative tools and tricks I&#8217;ve never seen before.&nbsp;<\/p>\n<p class=\"NB\"><strong>Why collaboration is key for teachers<\/strong><\/p>\n<p> Teachers have a hard job, not the least because if they can&#8217;t make it exciting every day, they&#8217;re not going to shoehorn much into the heads of the kids in the class.&nbsp; To do this, they&nbsp; have to make it &#8220;new&#8221; for themselves, as well.&nbsp;&nbsp;They&#8217;re always looking for new ways to look at their material, and often that means inviting their peers and mentors in, adding eyes and thoughts.&nbsp;<\/p>\n<p> If that weren&#8217;t enough, it often seems as though the <em>best<\/em> teachers treat their <em>students<\/em> as collaborators.&nbsp; Or maybe, depending on personality, as co-conspirators.&nbsp; Either way, the point is that ideas are shared, are built together, and the experience of learning&nbsp;builds on the give-and-take, not just the original lesson plan.<\/p>\n<p>In our district, we have used <a title=\"moodle community\" href=\"http:\/\/moodle.org\/\" target=\"_blank\" rel=\"noopener\">moodle<\/a> as a great way for experienced instructors to coach new teachers, and now it&#8217;s taking off for Distance Learning for students, as well.&nbsp; On both sites, the key is the collaboration fostered by the moodle environment, plus the ease with which people can construct and manage moodle content.<\/p>\n<h2>When the MySQL tutorial data is not enough<\/h2>\n<p>This week, looking for some new ideas for moodle add-in functionality, I found a list of web 2.0 apps in <em><a title=\"Campus Technology mag\" href=\"http:\/\/campustechnology.com\/Home\/\" target=\"_blank\" rel=\"noopener\">Campus Technology magazine<\/a>&nbsp;<\/em>.&nbsp; One of these tools also gave me a a great new&nbsp;way to gather&nbsp;sample reporting data: <a title=\"Factual.com site\" href=\"http:\/\/factual.com\" target=\"_blank\" rel=\"noopener\">Factual.com<\/a>.&nbsp;<\/p>\n<p><a title=\"Factual.com site\" href=\"http:\/\/factual.com\" target=\"_blank\" rel=\"noopener\">Factual<\/a>&nbsp;hosts what it calls a &#8220;living data ecosystem&#8221;, provided by its users and partners, enriched by data mining, aggregated and validated, and constantly improving.&nbsp; There are hundreds of thousands of datasets, in scores of categories (government, health, education, entertainment, etc).&nbsp; &#8216;<\/p>\n<p>No matter what type of data I might need to illustrate a point, I&#8217;ll find it there.<\/p>\n<h2>What&#8217;s the catch?<\/h2>\n<p>You can download CSV files interactively&nbsp;from <a title=\"Factual.com site\" href=\"http:\/\/factual.com\" target=\"_blank\" rel=\"noopener\">Factual<\/a>, which is okay as far as it goes, but not very exciting when you&#8217;re thinking about sourcing data for reports in an application.&nbsp;But <a title=\"Factual.com site\" href=\"http:\/\/factual.com\" target=\"_blank\" rel=\"noopener\">Factual<\/a> also allows you to grab data, complete with filters and other options, using a simple URL\/REST-ful API.&nbsp; That is perfect for my needs.&nbsp;<\/p>\n<p>BUT. The data comes back in <a title=\"read about JSON\" href=\"http:\/\/en.wikipedia.org\/wiki\/JSON\" target=\"_blank\" rel=\"noopener\">JSON<\/a>&#8230; and&nbsp;JSON is&nbsp;not so perfect as a datasource for SSRS.<\/p>\n<p>You may not dig Factual.com as much as I do, and you may not have to create sample datasets as often as I do&#8230; but I have a feeling you too will have reason to use JSON data at some point, and possibly want to analyze that data in an SSRS report&#8230;<\/p>\n<p>So, I thought I&#8217;d share what I did to convert&nbsp;Factual&nbsp;json&nbsp;for use in SSRS reports.&nbsp;&nbsp;My conversion method is&nbsp;very simple, and easily decoupled from the particulars of my scenario.&nbsp; It would work for any data you downloaded in JSON but wanted to stuff into an RDL, I think.<\/p>\n<h2>Quick and dirty JSON-sourcing for SSRS<\/h2>\n<p>Here are the three steps I&#8217;ll take, with the details and samples&nbsp;of what the data looks like at each step, so you can envision what&#8217;s going on:<\/p>\n<ol>\n<li>\n<p>Grab the data from its source,&nbsp;whatever that happens to be. In my case, that&#8217;s Factual, and&nbsp;the JSON return from its read method looks like this, per <a title=\"Factual read API description\" href=\"http:\/\/wiki.developer.factual.com\/w\/page\/29674488\/Read\" target=\"_blank\" rel=\"noopener\">http:\/\/wiki.developer.factual.com\/w\/page\/29674488\/Read<\/a>:<\/p>\n<table id=\"ccht\" class=\"pbNotSortable\" style=\"border-style: solid; border-color: silver;\" border=\"1\" cellspacing=\"0\">\n<tbody>\n<tr>\n<td style=\"border: 1px solid silver;\"><strong>Payload Field<\/strong><\/td>\n<td style=\"border: 1px solid silver;\"><strong>Description<\/strong><\/td>\n<td style=\"border: 1px solid silver;\"><strong>Examples<\/strong><\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid silver;\">fields<\/td>\n<td style=\"border: 1px solid silver;\">array of field names<\/td>\n<td style=\"border: 1px solid silver;\">&nbsp;<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid silver;\">data<\/td>\n<td style=\"border: 1px solid silver;\">array of rows, each of which is an array of cell values<\/td>\n<td style=\"border: 1px solid silver;\">[<br \/> [&#8216;a&#8217;,&#8217;b&#8217;,&#8217;c&#8217;]<br \/> [&#8216;e&#8217;,&#8217;f&#8217;,&#8217;g&#8217;]<br \/> ]<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid silver;\">subject_columns<\/td>\n<td style=\"border: 1px solid silver;\">Array of ordinals representing column(s) that make up the subject  (primary key) of the table (the subject key can always be used to identify a  row, but it can also be identified by subject label).  This index begins at  1.<\/td>\n<td style=\"border: 1px solid silver;\">[1]<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid silver;\">rows<\/td>\n<td style=\"border: 1px solid silver;\">integer value of rows contained in the data object<\/td>\n<td style=\"border: 1px solid silver;\">20<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid silver;\">total_rows<\/td>\n<td style=\"border: 1px solid silver;\">integer value of total rows available in the table (with the given  filter)<\/td>\n<td style=\"border: 1px solid silver;\">&nbsp;<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<p>&#8230; The example result I&#8217;m using in this post comes back looking like this:<\/p>\n<p class=\"code\">{&#8220;response&#8221;:{&#8220;total_rows&#8221;:26607,&#8221;data&#8221;:[[&#8220;YD7oKcCyu9ImD7Ozbjiuo4xZlZs&#8221;,&#8221;000098da-9b1c-4ea2-8ea0-ccb666336009&#8243;,&#8221;24 7 Available Locksmith&#8221;,&#8221;5121 Onacrest Dr&#8221;,&#8221;Los Angeles&#8221;,&#8221;CA&#8221;,&#8221;90043&#8243;,&#8221;(323) 545-3363&#8243;], <span style=\"color: #ff0000;\">&#8230; more rows here &#8230;. <\/span> ],&#8221;rows_is_estimated&#8221;:true,&#8221;fields&#8221;:[&#8220;subject_key&#8221;,&#8221;factual_id&#8221;,&#8221;name&#8221;,&#8221;address&#8221;,&#8221;locality&#8221;,&#8221;region&#8221;,&#8221;postcode&#8221;,&#8221;telephone&#8221;],&#8221;rows&#8221;:20,&#8221;cache-state&#8221;:&#8221;CACHED&#8221;,&#8221;big-data&#8221;:true,&#8221;subject_columns&#8221;:[1]},&#8221;version&#8221;:&#8221;2&#8243;,&#8221;status&#8221;:&#8221;ok&#8221;} <\/p>\n<p>&#8230; and as you can see this doesn&#8217;t match RDL expectations as-is, no matter how useful the data is.&nbsp; Onward!<\/p>\n<\/li>\n<li>\n<div>Use <a title=\"json.net codeplex home page\" href=\"http:\/\/json.codeplex.com\/\" target=\"_blank\" rel=\"noopener\">Json.NET<\/a>&nbsp; library (on codeplex, from NewtonSoft &#8212; visit <a title=\"read more about newtonsoft's json.net lib\" href=\"http:\/\/james.newtonking.com\/projects\/json-net\/\" target=\"_blank\" rel=\"noopener\">http:\/\/james.newtonking.com\/projects\/json-net<\/a>&nbsp;for more info) to transform the JSON source to an XML equivalent.&nbsp; No matter what your JSON format and characteristics, and this depends on your source, you need to do a test to see what the conversion will give you.&nbsp; In my case, each row appears as an&nbsp;element&nbsp; within a response element, with each column as a nested data element in a strict sequence.&nbsp;After all data rows appear, there is a set of fields elements, each one showing a column name for the data columns, and in the same sequence.&nbsp; It looks something like this:<\/div>\n<div class=\"code\">\n<pre lang=\"xml\"><span style=\"color: #0000ff;\">&lt;root&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\t<\/span><span style=\"color: #0000ff;\">&lt;!--<\/span><span style=\"color: #8c8c8c;\"> raw result from Newtonsoft.Json <\/span><span style=\"color: #0000ff;\">--&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\t<\/span><span style=\"color: #0000ff;\">&lt;response&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\t\t<\/span><span style=\"color: #0000ff;\">&lt;total_rows&gt;<\/span><span style=\"color: black; font-weight: bold;\">26607<\/span><span style=\"color: #0000ff;\">&lt;\/total_rows&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n<\/span><span style=\"color: black; font-weight: bold;\">\t\t<\/span><span style=\"color: #0000ff;\">&lt;data&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\t\t\t<\/span><span style=\"color: #0000ff;\">&lt;data&gt;<\/span><span style=\"color: black; font-weight: bold;\">YD7oKcCyu9ImD7Ozbjiuo4xZlZs<\/span><span style=\"color: #0000ff;\">&lt;\/data&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\t\t\t<\/span><span style=\"color: #0000ff;\">&lt;data&gt;<\/span><span style=\"color: black; font-weight: bold;\">000098da-9b1c-4ea2-8ea0-ccb666336009<\/span><span style=\"color: #0000ff;\">&lt;\/data&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\t\t\t<\/span><span style=\"color: #0000ff;\">&lt;data&gt;<\/span><span style=\"color: black; font-weight: bold;\">24 7 Available Locksmith<\/span><span style=\"color: #0000ff;\">&lt;\/data&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\t\t\t<\/span><span style=\"color: #0000ff;\">&lt;data&gt;<\/span><span style=\"color: black; font-weight: bold;\">5121 Onacrest Dr<\/span><span style=\"color: #0000ff;\">&lt;\/data&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\t\t\t<\/span><span style=\"color: #0000ff;\">&lt;data&gt;<\/span><span style=\"color: black; font-weight: bold;\">Los Angeles<\/span><span style=\"color: #0000ff;\">&lt;\/data&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\t\t\t<\/span><span style=\"color: #0000ff;\">&lt;data&gt;<\/span><span style=\"color: black; font-weight: bold;\">CA<\/span><span style=\"color: #0000ff;\">&lt;\/data&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\t\t\t<\/span><span style=\"color: #0000ff;\">&lt;data&gt;<\/span><span style=\"color: black; font-weight: bold;\">90043<\/span><span style=\"color: #0000ff;\">&lt;\/data&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\t\t\t<\/span><span style=\"color: #0000ff;\">&lt;data&gt;<\/span><span style=\"color: black; font-weight: bold;\">(323) 545-3363<\/span><span style=\"color: #0000ff;\">&lt;\/data&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\t\t<\/span><span style=\"color: #0000ff;\">&lt;\/data&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\t\t<\/span><span style=\"color: #0000ff;\">&lt;!--<\/span><span style=\"color: #8c8c8c;\"> ... more &lt;data\/&gt; elements here ... followed by: <\/span><span style=\"color: #0000ff;\">--&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\t\t<\/span><span style=\"color: #0000ff;\">&lt;rows_is_estimated&gt;<\/span><span style=\"color: black; font-weight: bold;\">true<\/span><span style=\"color: #0000ff;\">&lt;\/rows_is_estimated&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\t\t<\/span><span style=\"color: #0000ff;\">&lt;fields&gt;<\/span><span style=\"color: black; font-weight: bold;\">subject_key<\/span><span style=\"color: #0000ff;\">&lt;\/fields&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\t\t<\/span><span style=\"color: #0000ff;\">&lt;fields&gt;<\/span><span style=\"color: black; font-weight: bold;\">factual_id<\/span><span style=\"color: #0000ff;\">&lt;\/fields&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\t\t<\/span><span style=\"color: #0000ff;\">&lt;fields&gt;<\/span><span style=\"color: black; font-weight: bold;\">name<\/span><span style=\"color: #0000ff;\">&lt;\/fields&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\t\t<\/span><span style=\"color: #0000ff;\">&lt;fields&gt;<\/span><span style=\"color: black; font-weight: bold;\">address<\/span><span style=\"color: #0000ff;\">&lt;\/fields&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\t\t<\/span><span style=\"color: #0000ff;\">&lt;fields&gt;<\/span><span style=\"color: black; font-weight: bold;\">locality<\/span><span style=\"color: #0000ff;\">&lt;\/fields&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\t\t<\/span><span style=\"color: #0000ff;\">&lt;fields&gt;<\/span><span style=\"color: black; font-weight: bold;\">region<\/span><span style=\"color: #0000ff;\">&lt;\/fields&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\t\t<\/span><span style=\"color: #0000ff;\">&lt;fields&gt;<\/span><span style=\"color: black; font-weight: bold;\">postcode<\/span><span style=\"color: #0000ff;\">&lt;\/fields&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\t\t<\/span><span style=\"color: #0000ff;\">&lt;fields&gt;<\/span><span style=\"color: black; font-weight: bold;\">telephone<\/span><span style=\"color: #0000ff;\">&lt;\/fields&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\t\t<\/span><span style=\"color: #0000ff;\">&lt;rows&gt;<\/span><span style=\"color: black; font-weight: bold;\">20<\/span><span style=\"color: #0000ff;\">&lt;\/rows&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\t\t<\/span><span style=\"color: #0000ff;\">&lt;cache-state&gt;<\/span><span style=\"color: black; font-weight: bold;\">CACHED<\/span><span style=\"color: #0000ff;\">&lt;\/cache-state&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\t\t<\/span><span style=\"color: #0000ff;\">&lt;big-data&gt;<\/span><span style=\"color: black; font-weight: bold;\">true<\/span><span style=\"color: #0000ff;\">&lt;\/big-data&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\t\t<\/span><span style=\"color: #0000ff;\">&lt;subject_columns&gt;<\/span><span style=\"color: black; font-weight: bold;\">1<\/span><span style=\"color: #0000ff;\">&lt;\/subject_columns&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\t<\/span><span style=\"color: #0000ff;\">&lt;\/response&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\t<\/span><span style=\"color: #0000ff;\">&lt;version&gt;<\/span><span style=\"color: black; font-weight: bold;\">2<\/span><span style=\"color: #0000ff;\">&lt;\/version&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\t<\/span><span style=\"color: #0000ff;\">&lt;status&gt;<\/span><span style=\"color: black; font-weight: bold;\">ok<\/span><span style=\"color: #0000ff;\">&lt;\/status&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n<\/span><span style=\"color: #0000ff;\">&lt;\/root&gt;<br \/><\/span><\/pre>\n<\/div>\n<p>&nbsp; <\/li>\n<li> Transform&nbsp;the XML you got in the last step to something ADO-shaped.&nbsp; My XSLT for this is simplicity itself.&nbsp; I&#8217;m creating attribute-centric rows, because they&#8217;re a little more compact, but you can make them element-centric if you prefer (just change the &lt;xsl:attribute&gt; to &lt;xsl:element&gt;).&nbsp; Each attribute (or element) is deriving its name from the corresponding field or column name that we got from the JSON fields collection:&nbsp;\n<div class=\"code\">\n<pre lang=\"xml\"><span style=\"color: #0000ff;\">&lt;?<\/span><span style=\"color: #004080;\">xml version<\/span><span style=\"color: #0000ff;\">=\"<\/span><span style=\"color: black; font-weight: bold;\">1.0<\/span><span style=\"color: #0000ff;\">\"<\/span><span style=\"color: #004080;\"> encoding<\/span><span style=\"color: #0000ff;\">=\"<\/span><span style=\"color: black; font-weight: bold;\">utf-8<\/span><span style=\"color: #0000ff;\">\"?&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n<\/span><span style=\"color: #0000ff;\">&lt;xsl:stylesheet<\/span><span style=\"color: #be3232;\"> version<\/span><span style=\"color: #0000ff;\">=\"<\/span><span style=\"color: black; font-weight: bold;\">1.0<\/span><span style=\"color: #0000ff;\">\"<\/span><span style=\"color: #be3232;\"> xmlns:xsl<\/span><span style=\"color: #0000ff;\">=\"<\/span><span style=\"color: black; font-weight: bold;\">http:\/\/www.w3.org\/1999\/XSL\/Transform<\/span><span style=\"color: #0000ff;\">\"&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n    <\/span><span style=\"color: #0000ff;\">&lt;xsl:output<\/span><span style=\"color: #be3232;\"> method<\/span><span style=\"color: #0000ff;\">=\"<\/span><span style=\"color: black; font-weight: bold;\">xml<\/span><span style=\"color: #0000ff;\">\"<\/span><span style=\"color: #be3232;\"> omit-xml-declaration <\/span><span style=\"color: #0000ff;\">=\"<\/span><span style=\"color: black; font-weight: bold;\">yes<\/span><span style=\"color: #0000ff;\">\"\/&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\n  <\/span><span style=\"color: #0000ff;\">&lt;xsl:variable<\/span><span style=\"color: #be3232;\"> name<\/span><span style=\"color: #0000ff;\">=\"<\/span><span style=\"color: black; font-weight: bold;\">cols<\/span><span style=\"color: #0000ff;\">\"<\/span><span style=\"color: #be3232;\"> select <\/span><span style=\"color: #0000ff;\">=\"<\/span><span style=\"color: black; font-weight: bold;\">\/*\/response\/fields<\/span><span style=\"color: #0000ff;\">\"\/&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\n  <\/span><span style=\"color: #0000ff;\">&lt;xsl:template<\/span><span style=\"color: #be3232;\"> match<\/span><span style=\"color: #0000ff;\">=\"<\/span><span style=\"color: black; font-weight: bold;\">\/<\/span><span style=\"color: #0000ff;\">\"&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n    <\/span><span style=\"color: #0000ff;\">&lt;Rows&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n      <\/span><span style=\"color: #0000ff;\">&lt;xsl:apply-templates<\/span><span style=\"color: #be3232;\"> select<\/span><span style=\"color: #0000ff;\">=\"<\/span><span style=\"color: black; font-weight: bold;\">\/*\/response\/data<\/span><span style=\"color: #0000ff;\">\"\/&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n    <\/span><span style=\"color: #0000ff;\">&lt;\/Rows&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n  <\/span><span style=\"color: #0000ff;\">&lt;\/xsl:template&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\n  <\/span><span style=\"color: #0000ff;\">&lt;xsl:template<\/span><span style=\"color: #be3232;\"> match<\/span><span style=\"color: #0000ff;\">=\"<\/span><span style=\"color: black; font-weight: bold;\">response\/data<\/span><span style=\"color: #0000ff;\">\"&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n    <\/span><span style=\"color: #0000ff;\">&lt;Row<\/span><span style=\"color: #be3232;\"> ID<\/span><span style=\"color: #0000ff;\">=\"<\/span><span style=\"color: black; font-weight: bold;\">{count(preceding-sibling::*)}<\/span><span style=\"color: #0000ff;\">\"&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n    <\/span><span style=\"color: #0000ff;\">&lt;xsl:for-each<\/span><span style=\"color: #be3232;\"> select <\/span><span style=\"color: #0000ff;\">=\"<\/span><span style=\"color: black; font-weight: bold;\">.\/data<\/span><span style=\"color: #0000ff;\">\"&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n      <\/span><span style=\"color: #0000ff;\">&lt;xsl:variable<\/span><span style=\"color: #be3232;\"> name<\/span><span style=\"color: #0000ff;\">=\"<\/span><span style=\"color: black; font-weight: bold;\">pos<\/span><span style=\"color: #0000ff;\">\"<\/span><span style=\"color: #be3232;\"> select <\/span><span style=\"color: #0000ff;\">=\"<\/span><span style=\"color: black; font-weight: bold;\">position()<\/span><span style=\"color: #0000ff;\">\"\/&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n      <\/span><span style=\"color: #0000ff;\">&lt;xsl:attribute<\/span><span style=\"color: #be3232;\"> name<\/span><span style=\"color: #0000ff;\">=\"<\/span><span style=\"color: black; font-weight: bold;\">{$cols[position() = $pos]}<\/span><span style=\"color: #0000ff;\">\"&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n        <\/span><span style=\"color: #0000ff;\">&lt;xsl:value-of<\/span><span style=\"color: #be3232;\"> select<\/span><span style=\"color: #0000ff;\">=\"<\/span><span style=\"color: black; font-weight: bold;\">.<\/span><span style=\"color: #0000ff;\">\"\/&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n      <\/span><span style=\"color: #0000ff;\">&lt;\/xsl:attribute&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n    <\/span><span style=\"color: #0000ff;\">&lt;\/xsl:for-each&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n    <\/span><span style=\"color: #0000ff;\">&lt;\/Row&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n    <\/span><span style=\"color: #0000ff;\">&lt;\/xsl:template&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n\n<\/span><span style=\"color: #0000ff;\">&lt;\/xsl:stylesheet&gt;<\/span><span style=\"color: black; font-weight: bold;\">\n<\/span><\/pre>\n<\/div>\n<p>&#8230; and the result looks pretty much like you would expect, very generic, kind of boring, but okay for an RDL dataset:&nbsp;<\/p>\n<div class=\"code\">\n<pre lang=\"xml\"><span style=\"color: #0000ff;\">&lt;Rows&gt;<br \/><\/span><span style=\"color: #0000ff;\">&lt;Row<\/span><span style=\"color: #be3232;\"> ID<\/span><span style=\"color: #0000ff;\">=\"<\/span><span style=\"color: black; font-weight: bold;\">1<\/span><span style=\"color: #0000ff;\">\"<\/span><span style=\"color: #be3232;\"> <br \/>   subject_key<\/span><span style=\"color: #0000ff;\">=\"<\/span><span style=\"color: black; font-weight: bold;\">YD7oKcCyu9ImD7Ozbjiuo4xZlZs<\/span><span style=\"color: #0000ff;\">\"<br \/><\/span><span style=\"color: #be3232;\">   factual_id<\/span><span style=\"color: #0000ff;\">=\"<\/span><span style=\"color: black; font-weight: bold;\">000098da-9b1c-4ea2-8ea0-ccb666336009<\/span><span style=\"color: #0000ff;\">\"<\/span><span style=\"color: #be3232;\"> <br \/>   name<\/span><span style=\"color: #0000ff;\">=\"<\/span><span style=\"color: black; font-weight: bold;\">24 7 Available Locksmith<\/span><span style=\"color: #0000ff;\">\"<\/span><span style=\"color: #be3232;\"> address<\/span><span style=\"color: #0000ff;\">=\"<\/span><span style=\"color: black; font-weight: bold;\">5121 Onacrest Dr<\/span><span style=\"color: #0000ff;\">\"<br \/><\/span><span style=\"color: #be3232;\">   locality<\/span><span style=\"color: #0000ff;\">=\"<\/span><span style=\"color: black; font-weight: bold;\">Los Angeles<\/span><span style=\"color: #0000ff;\">\"<\/span><span style=\"color: #be3232;\"> region<\/span><span style=\"color: #0000ff;\">=\"<\/span><span style=\"color: black; font-weight: bold;\">CA<\/span><span style=\"color: #0000ff;\">\"<\/span><span style=\"color: #be3232;\"> postcode<\/span><span style=\"color: #0000ff;\">=\"<\/span><span style=\"color: black; font-weight: bold;\">90043<\/span><span style=\"color: #0000ff;\">\"<br \/>   <\/span><span style=\"color: #be3232;\">telephone<\/span><span style=\"color: #0000ff;\">=\"<\/span><span style=\"color: black; font-weight: bold;\">(323) 545-3363<\/span><span style=\"color: #0000ff;\">\"<\/span><span style=\"color: #be3232;\"> <\/span><span style=\"color: #0000ff;\">\/&gt;<br \/><br \/><\/span><span style=\"color: #0000ff;\"><strong><span style=\"color: #000000;\">&nbsp; <\/span><\/strong><span style=\"color: #0000ff;\">&lt;!--<\/span><span style=\"color: #8c8c8c;\"> ... lots more &lt;Row\/&gt; elements here ... ending with: <\/span><span style=\"color: #0000ff;\">--&gt;<\/span><span style=\"color: black; font-weight: bold;\"> <br \/><\/span><br \/>&lt;\/Rows&gt;<\/span>\n<br \/><\/pre>\n<\/div>\n<\/li>\n<\/ol>\n<h2>How&#8217;s that again?<\/h2>\n<p>Here are the gory details of HOW to take the steps I just listed, in their code-ish entirety, as I wrote them in an ASP.NET page method.<\/p>\n<p>If you don&#8217;t count a couple of import statements to reference standard .NET libs plus Newtonsoft.Json,&nbsp;<strong>this is absolutely all the code there is<\/strong> behind my simple little web service-y page, and wherever you decided to house the code, it would look about the same, or even simpler (because you might not need the a Response-specific flushing and closing): <\/p>\n<div class=\"code\"><span style=\"color: #0000ff;\">Protected Sub<\/span> Page_Load( \t<span style=\"color: #0000ff;\">ByVal<\/span> sender \t<span style=\"color: #0000ff;\">As Object<\/span>, \t<span style=\"color: #0000ff;\">ByVal<\/span> e \t<span style=\"color: #0000ff;\">As<\/span> System.<span style=\"color: #2b91af;\">EventArgs<\/span>)    <span style=\"color: #0000ff;\">Handles Me<\/span>.Load<br \/> <span style=\"color: #0000ff;\">&nbsp;&nbsp;&nbsp; <br \/>&nbsp;&nbsp;&nbsp; Dim<\/span> jsonText <span style=\"color: #0000ff;\">As String<\/span><br \/> &nbsp;&nbsp; \t<span style=\"color: #0000ff;\">&nbsp;<\/span>&nbsp; \t<span style=\"color: #008000;\"> &#8216; I&#8217;ll be getting this directly from factual.com<\/span> <\/p>\n<p> <span style=\"color: #0000ff;\"> &nbsp;&nbsp;&nbsp; Dim <\/span> client \t<span style=\"color: #0000ff;\">As New<\/span> <span style=\"color: #2b91af;\">WebClient<\/span> (),    url \t<span style=\"color: #0000ff;\"> As String<\/span><br \/>&nbsp;<span style=\"color: #008000;\">&nbsp;&nbsp; &#8216;    First, decide where to get the data you want:<\/span><br \/> &nbsp;&nbsp;&nbsp; url = <span style=\"color: #a31515;\">&#8220;http:\/\/api.factual.com\/v2\/tables\/YourTableID\/read?APIKey=YourApiKey&#8221;<\/span> <br \/> <span style=\"color: #008000;\"> &nbsp;&nbsp;&nbsp; &#8216;    To build this url properly in an app, we might have to parse incoming variables <br \/> &nbsp;&nbsp;&nbsp; &#8216;    and fashion a querystring on the URL rather than just&nbsp;pasting in&nbsp;a literal&nbsp;as shown&nbsp;here \t\t<br \/>&nbsp;&nbsp;&nbsp;<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8216;    Once the url is built, get the data: <\/span><br \/> &nbsp;&nbsp;&nbsp; json = client.DownloadString(url)<\/p>\n<p> <span style=\"color: #008000;\">&nbsp;&nbsp; &#8216; Now get xml from Factual&#8217;s JSON response:<\/span> <br \/> &nbsp;&nbsp;&nbsp; \t<span style=\"color: #0000ff;\">Dim<\/span> doc <span style=\"color: #0000ff;\">As <\/span> <span style=\"color: #2b91af;\">XmlDocument<\/span>=&nbsp; _ \t<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style=\"color: #0000ff;\">CType<\/span>(<span style=\"color: #2b91af;\">JsonConvert<\/span>.DeserializeXmlNode(jsonText,    <span style=\"color: #a31515;\">&#8220;root&#8221;<\/span>), \t<span style=\"color: #2b91af;\">XmlDocument<\/span>) \t<\/p>\n<p> <span style=\"color: #008000;\"> &nbsp;&nbsp;&nbsp; &#8216; Convert the json-based XML    according to what Newtonsoft will do,<br \/> &nbsp;&nbsp;&nbsp; &#8216;    to ADO-shaped XML, very generically : <\/span><\/p>\n<p> <span style=\"color: #0000ff;\">&nbsp;&nbsp;&nbsp; Dim<\/span> xsl <span style=\"color: #0000ff;\">As New<\/span> <span style=\"color: #2b91af;\">XslCompiledTransform<\/span>(),    result <span style=\"color: #0000ff;\">As New<\/span> <span style=\"color: #2b91af;\">StringWriter<\/span>() \t\t<\/p>\n<p> &nbsp;&nbsp;&nbsp; xsl.Load(Server.MapPath( <span style=\"color: #a31515;\">&#8220;NewtonsoftStyleFactual.To.AdoStyleFactual.xslt&#8221;<\/span>))    <br \/> &nbsp;&nbsp;&nbsp; \t<span style=\"color: #008000;\"> &#8216; I should be caching this,    it will always be the same <\/span><\/p>\n<p> &nbsp;&nbsp;&nbsp; xsl.Transform(doc,    <span style=\"color: #0000ff;\">Nothing<\/span>, result)<br \/> &nbsp;&nbsp;&nbsp; result.Close()<br \/> &nbsp;&nbsp;&nbsp; result.Flush()<br \/> <span style=\"color: #008000;\"> <br \/> &nbsp;&nbsp;&nbsp; &#8216; &#8230; And the result you&#8217;ll send back will be usable in a    report: <\/span><br \/>&nbsp;&nbsp;&nbsp; Response.ContentType    = <span style=\"color: #a31515;\">&#8220;application\/xml&#8221;<\/span><br \/> &nbsp;&nbsp;<span style=\"color: #a31515;\">&nbsp; <\/span> Response.Write(result.ToString())<br \/> &nbsp;&nbsp;&nbsp; Response.Flush()<br \/> &nbsp;&nbsp;&nbsp; Response.End()<\/p>\n<p> <span style=\"color: #0000ff;\">End Sub<\/span><\/div>\n<div>&nbsp;<\/div>\n<h2>How does the report &#8220;read&#8221; it?<\/h2>\n<p><span style=\"background-color: #ffff00;\"><span style=\"background-color: #ffffff;\">If you&#8217;re just playing around with sample data, you can do most of this interactively in Visual Studio &#8212; I&#8217;ve written <a title=\"blog post about running an xslt transform interactively from Visual Studio\" href=\"\/lisa\/2009\/02\/07\/YAPS-Random-acts-of-kindness-regarding-Reports-Excel-XSLT-and-you\/\">elsewhere<\/a> about how to&nbsp;use Visual Studio or other tools to do the XSLT transform part.&nbsp; If you&#8217;re going to do it repeatedly, you can <\/span><span style=\"background-color: #ffffff;\">incorporate the code you see above, including the&nbsp;Newsonsoft translation, into&nbsp;a small executable that takes a couple of parameters, so that you can easily create a sample data set in easy-to-use XML form for reporting in a couple of seconds.<\/span><\/span><\/p>\n<p>Once you have that XML&nbsp;content available, you can actually embed the full XML document into the RDL&nbsp;if you want.&nbsp; This is a good idea if you&#8217;re just playing around with a new JSON-based data source.&nbsp; The XML goes, strangely enough, directly into the Query Builder &#8212; there&#8217;s an entry in the docs titled <strong>XML Query Syntax for Specifying XML Report Data<\/strong> that provides an example.&nbsp; Basically you put XML similar to what we&#8217;ve created inside the following nodes, written right into the Query Builder in place of a SQL statement or reference to a code function:&nbsp;<\/p>\n<div class=\"code\">&lt;Query&gt;<br \/> &nbsp;&nbsp; &lt;XmlData&gt;<br \/> <span style=\"color: red;\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;!&#8211; our entire XML data document goes here &#8211;&gt;<\/span><br \/> &nbsp;&nbsp; &lt;\/XmlData&gt;<br \/> &lt;\/Query&gt;<\/div>\n<p>If you&#8217;re using an RDLC, it&#8217;s even easier, even if this is production work rather than a &#8220;play-round&#8221;.&nbsp;&nbsp;You can easily load the final product of<span style=\"background-color: #ffffff;\"> the code in the method above <\/span>into a dataset, &nbsp;and hand&nbsp;that dataset&nbsp;to a report, in whatever type of&nbsp;application is doing the rest of your work and hosting the reportviewer control.&nbsp;You can read <a title=\"blog post about dynamically loading up reportviewer controls\" href=\"\/lisa\/2007\/09\/19\/Dynamically-loading-reports-in-ReportViewers\/\">here<\/a>&nbsp;&nbsp;for&nbsp;one of my&nbsp;examples of&nbsp;dynamically creating a datasource for a local report &#8212; or just go to <a title=\"GotReportViewer tutorial site\" href=\"http:\/\/gotreportviewer.com\" target=\"_blank\" rel=\"noopener\">http:\/\/gotreportviewer.com<\/a>, and learn about local reports from the ground-up. &nbsp;<\/p>\n<p>If you&#8217;re using an RDL, and if this is a production app, obviously you are <em>not<\/em> going to embed the XML data into the RDL the way you did for tests; there will be parameters, and the data will be live and dynamic.&nbsp; You have to use a &#8220;real&#8221; xml data source now.&nbsp;<\/p>\n<p>This part will take a little more work than you&#8217;re used to, when pulling data from a &#8220;real&#8221; relational database, but only a little.<\/p>\n<div class=\"NB\" style=\"padding-left: 30px;\">Caveat: what I&#8217;m about to show you works perfectly in Visual Studio 2010. But in Visual Studio 2008 you will run into a couple of obstacles.&nbsp; <\/p>\n<p>If you&#8217;re in Visual Studio 2008, I found that (besides manually editing the XML), it was best to start off creating the report in Report Builder; Report Designer had a couple of nasty bugs as you create and configure the data source.&nbsp; After I got through&nbsp;that initial work, I couldn&#8217;t layout and preview the RDL in Report Builder, because it wasn&#8217;t happy with the authentication requirements for the XML Data Source, even though it created&nbsp;the darn thing.&nbsp; However, I could save the RDL to disk, and I was then able to design the report layout, and preview it properly, using Report Designer in Visual Studio 2008.<\/p><\/div>\n<p>Here&#8217;s what you do.<\/p>\n<table style=\"border: 1px solid silver;\" border=\"1\" cellspacing=\"0\">\n<tbody>\n<tr>\n<td style=\"border: 1px solid silver;\">First, as Steve Martin would have said,&nbsp;give the RDL&nbsp;a new XML data source.&nbsp; I mean, the TYPE of the connection is XML.&nbsp; Seems obvious, but I can&#8217;t tell you how many times I&#8217;ve done the next step and not noticed that the stupid drop down reverted to SQL Server while I wasn&#8217;t looking.<\/td>\n<td style=\"border: 1px solid silver;\"><img decoding=\"async\" src=\"\/lisa\/wp-non\/migrated\/2011\/10\/ds1.png\" alt=\"Starting a new XML data source in an RDL\" \/><\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid silver;\">The connection string for your new data source is going to be the URL for the web-service-y little ASP.NET page you&#8217;ve constructed to go get your data.<\/td>\n<td style=\"border: 1px solid silver;\">&nbsp; <img decoding=\"async\" src=\"\/lisa\/wp-non\/migrated\/2011\/10\/ds2.png\" alt=\"call the 'web service'\" \/><\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid silver;\">\n<div>Now create a dataset using this data source.&nbsp; Your &#8220;Query&#8221; will be a strange-looking XPATH-y expression, that basically drills down from the root node (mine is &#8220;Rows&#8221;) to the datarow-level element I want for each row in the result (mine is &#8220;Row&#8221;).&nbsp;&nbsp;&nbsp; For more info, search for <strong><span id=\"nsrTitle\">Element Path Syntax for Specifying XML Report Data <\/span><\/strong>in the docs.<\/div>\n<div>When you press the &#8220;Refresh Fields&#8221; button, nothing will appear to happen &#8212; but the Dataset will, in fact, get its fields collection.&nbsp; You can verify this by going into the Query Designer window; you&#8217;ll see your data.&nbsp; Make sure you do this <em>before<\/em> trying to set up the connection as an expression (see next step).<\/div>\n<\/td>\n<td style=\"border: 1px solid silver;\"><img decoding=\"async\" src=\"\/lisa\/wp-non\/migrated\/2011\/10\/ds4.png\" alt=\"\" \/><\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid silver;\">Don&#8217;t forget that the &#8220;connection string&#8221; (aka URL) can be an expression.  You&#8217;ll need this if you are going to pass some filtering or limiting instructions, or other options, to the JSON source, as I will for Factual. <\/td>\n<td style=\"border: 1px solid silver;\"><img decoding=\"async\" src=\"\/lisa\/wp-non\/migrated\/2011\/10\/ds3.png\" alt=\"use an expression to pass information to the datasource\" \/><\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid silver;\" colspan=\"2\" valign=\"top\">If you use an expression right away (before building your fields collection for the dataset), you&#8217;ve made it difficult for the Report Designer to cache some data for layout purposes; you&#8217;ll get an error and you&#8217;ll have to manually create your fields collection, which can be done but is a PITA.<br \/>&nbsp;<\/p>\n<div style=\"padding-left: 30px;\"><img decoding=\"async\" src=\"\/lisa\/wp-non\/migrated\/2011\/10\/ds0.png\" alt=\"\" \/><\/div>\n<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid silver;\">It&#8217;s a little extra trouble, but that&#8217;s it!<\/p>\n<p> Afterwards, you just use the data set and design the report as you normally would.<\/td>\n<td style=\"border: 1px solid silver;\"><img decoding=\"async\" src=\"\/lisa\/wp-non\/migrated\/2011\/10\/ds5.png\" alt=\"\" \/><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>It&#8217;s definitely worth it<\/h2>\n<p>Almost anything I could ever want for sample data &#8212; and a lot I&#8217;d want for production BI reference use as well &#8212; can be found at Factual.com.&nbsp; And I&#8217;ll never have to write another line of code to convert it again, except for whatever intelligent parameters, specific to each data set, I might want to expose and pass back in the URL.&nbsp;<\/p>\n<p>As a corollary, almost any kind of data, besides JSON, could be expressed as XML using the same methodology and &#8220;thrown&#8221; over the fence to an RDL using an XML data source, with no additional code being written.<\/p>\n<p>What do you think?&nbsp;Fun, or what?&nbsp;<\/p>\n<p>C&#8217;mon.&nbsp; If you like data and reports, you gotta say *yeah*.<\/p>\n<div>&nbsp;<\/div>\n","protected":false},"excerpt":{"rendered":"<p>One of the fun things about my job is its constant exposure to collaborative tools and tricks I&#8217;ve never seen before.&nbsp; Why collaboration is key for teachers Teachers have a hard job, not the least because if they can&#8217;t make it exciting every day, they&#8217;re not going to shoehorn much into the heads of the<a class=\"more-link\" href=\"https:\/\/spacefold.com\/lisa\/2011\/10\/14\/actual-factual-json-data-in-ssrs\/\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,5,10],"tags":[],"class_list":["post-57","post","type-post","status-publish","format-standard","hentry","category-asp-net","category-reporting","category-xml-xslt"],"_links":{"self":[{"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/posts\/57","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/comments?post=57"}],"version-history":[{"count":0,"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/posts\/57\/revisions"}],"wp:attachment":[{"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/media?parent=57"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/categories?post=57"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/tags?post=57"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}