{"id":165,"date":"2007-10-28T01:35:00","date_gmt":"2007-10-28T01:35:00","guid":{"rendered":"\/lisa\/post\/2007\/10\/28\/After-you-learn-to-walk-you-can-run-a-postscript-to-the-QnD-XSLT-walkthrough.aspx"},"modified":"2007-10-28T01:35:00","modified_gmt":"2007-10-28T01:35:00","slug":"after-you-learn-to-walk-you-can-run-a-postscript-to-the-qnd-xslt-walkthrough","status":"publish","type":"post","link":"https:\/\/spacefold.com\/lisa\/2007\/10\/28\/after-you-learn-to-walk-you-can-run-a-postscript-to-the-qnd-xslt-walkthrough\/","title":{"rendered":"After you learn to walk, you can run: a postscript to the QnD XSLT walkthrough"},"content":{"rendered":"<p>\nWhen I&nbsp;<a href=\"\/lisa\/2007\/10\/03\/Changing-the-Sheet-names-in-SQL-Server-RS-Excel-QnD-XSLT\/\" title=\"RS Excel QnD XSLT\">posted&nbsp;about using XSLT to create customized Excel<\/a> in SQL Server Reporting Services, starting from RS&#39;s XML Data format, I deliberately included a step that allowed&nbsp;the reader&nbsp;to automagically attach the XSLT to your Reporting Services process:\n<\/p>\n<blockquote>\n<p>\n\tNow attach your XSLT document to the report by putting its name in the Data Output tab of the Report Properties dialog. <a href=\"\/lisa\/wp-non\/migrated\/AttachXSLTToRDLDataOutput.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" src=\"\/lisa\/wp-non\/migrated\/preview.png\" border=\"0\" alt=\"\" title=\"See what I'm talking \n\tabout?\" width=\"12\" height=\"12\" align=\"textTop\" \/><\/a>\n\t<\/p>\n<\/blockquote>\n<p>\nTelling the RDL about your XSLT&nbsp;allows you to do things in one step.&nbsp; In the context of the walkthrough, the reader is not distracted by thinking about adding any wrapper process or additional code to perform the transformation step.&nbsp;\n<\/p>\n<p>\nWhich is fine, as far as it goes.&nbsp;\n<\/p>\n<p>\nBut I really want people to understand that adding an XSLT transform explicitly, in your own code, is&nbsp;far better. It takes only&nbsp;a few lines of code, in pretty much any programming environment to do, but that&#39;s why it&#39;s easy, not why it&#39;s better.\n<\/p>\n<h3>Why is it better?<\/h3>\n<p>\nWhen you extract data as XML from your reporting resource, you have the data you need for multiple presentations.&nbsp;XSLT supplies the means to create those multiple presentations. If you add the name of the XSLT to your RDL as a part of the Data Output handling, you give up the ability to have, well, multiple outputs.&nbsp; If you wanted a second result, you&#39;d need to load a different RDL with a different XSLT specified.&nbsp; You could probably mess with the original RDL and load it dynamically with a different XSLT value, but &quot;mess&quot; is the operative word here.\n<\/p>\n<p class=\"NB\">\nThis division between the &quot;automagic&quot; attachment of a single XSLT and the real extension behavior we&#39;d prefer&nbsp;isn&#39;t a particular failure of RDLs or of Reporting Services. It&#39;s pretty common among generic processes to try to make things easier for you to try out, and to lose some significant functionality in the process of making things easier.&nbsp; The idea is that you&#39;ll get the hint of how much more you can do, by using the in-the-box capability and that you will&#8230; go on to do more.\n<\/p>\n<p>\nWhen you don&#39;t load the XSLT yourself, you lose more than just the flexibility to specify the XSLT to load. You also lose the ability to <em>parameterize <\/em>one XSLT to handle different features or sets of options.&nbsp;\n<\/p>\n<p>\nImagine, for example, that your report has a dynamic&nbsp;colorset feature, or localization feature, and you&#39;d like the XSLT to know what the user has specified for this run.&nbsp;&nbsp; Or imagine that you&#39;d like to pass on the User!UserID value from Reporting Services, to lookup&nbsp;access rights associated with UserID values and apply visibility dynamically on that basis.&nbsp; (One of the things that most people don&#39;t realize about XSLT is that you can supply a whole document, such as the XML for those user rights, as a parameter, and you can search the contents of that document, along with the XSLT document itself, using XPATH, just as you search the source XML document.)\n<\/p>\n<p>\nThe automagic processes usually don&#39;t make room for&nbsp;parameterizing XSLT.&nbsp; This is true even for automagic as far afield from RS, and as tightly integrated with XML, as Oracle BPEL-Workflow. Apparently it is possible&nbsp;in that environment&nbsp;<a href=\"http:\/\/blogs.oracle.com\/rammenon\/discuss\/msgReader$9\" target=\"_blank\" title=\"kludge for XSLT parameters in Oracle Workflow\" rel=\"noopener\">with a kludge<\/a> &#8212; but I can&#39;t&nbsp;imagine why they didn&#39;t build&nbsp;in parameter handling&nbsp;in as soon as they decided to expose an XSLT task type. Caveat: they may have done it by now, I haven&#39;t checked recently.&nbsp;&nbsp;\n<\/p>\n<p>\nThis particular omission&nbsp;really bugs me, and I could make a case for how RS, at least,&nbsp;could have automagically supplied&nbsp;the report&#39;s parameters to the XSLT, whether they were needed or not, since XSLT processors will accept such an assignment even when the parameters aren&#39;t defined.&nbsp;\n<\/p>\n<p>\nNever mind.&nbsp; The point is not to Monday-morning-quarterback the automagic processes offered by vendors.&nbsp; The point is using them as a starting point, and continuing your journey on from there. In this case, again, it&#39;s really easy to do.\n<\/p>\n<h3>So, how is it easy?<\/h3>\n<p>\nYou can apply an XSLT transformation using COM or .NET or Java or PHP or whatever you like.&nbsp; In <a href=\"\/lisa\/2007\/08\/03\/Introducing-XMLRSDocs-and-RDLDocumenter\/\" title=\"Introducing RDLDocumenter\">RDLDocumenter<\/a>&#39;s production processing, as you can see when you explore the DTSX file, &nbsp;I&#39;m using an SSIS XML task to do the job and frankly I have no idea what classes it decides to use for the purpose.&nbsp;\n<\/p>\n<p>\nIn RDLDocumenter&#39;s TestHarness, I&#39;m using a .Net Framework class called Xml.Xsl.XslCompiledTransform. I like this class very much and would recommend that you look into it&nbsp;for your own production work.&nbsp;You don&#39;t lose the dynamic value of XSLT parameters just because you&#39;ve pre-compiled the transformation document; the parameters are applied fresh on each transformation action.\n<\/p>\n<p>\nRDLDocumenter also comes supplied with a couple of sample SQL and VBS scripts, one of which shows how you can use COM objects in VFP or VBS to apply a transformation.&nbsp; The VBS script which supplies this code&nbsp;is a sample showing you how&nbsp;you might transform&nbsp;RDLs into the docRDL format without going through the TestHarness form interface or anything fancy to do it.&nbsp;(Similarly, one of the SQL&nbsp;sample scripts shows you how to use SQL to shred the XML into database tables without any external or CLR code if you happen not to&nbsp;want to use any.&nbsp; The idea was to stress that it&#39;s not the technology you use to do it that&#39;s important in&nbsp;XMLRSDocs. Not by a long shot.)&nbsp;\n<\/p>\n<p>\nThe&nbsp;VBS&nbsp;script does something like this:\n<\/p>\n<p class=\"code\">\n<font color=\"#0000ff\">Set<\/font> ox = WScript.CreateObject(<font color=\"#a31515\">&quot;Microsoft.Xmldom&quot;<\/font>)<br \/>\nox.Load(source)<br \/>\n<font color=\"#0000ff\">Set<\/font> oy = WScript.CreateObject(<font color=\"#a31515\">&quot;Microsoft.Xmldom&quot;<\/font>)<br \/>\n<font color=\"#0000ff\">If<\/font> args.Count &gt; 1 <font color=\"#0000ff\">Then<br \/>\n<\/font>&nbsp;&nbsp; oy.Load(args.Item(1))<br \/>\n<font color=\"#0000ff\">Else<br \/>\n<\/font><font color=\"#008000\">&nbsp;&nbsp; &#39; ..\\Deploy\\EditableResources\\xmlRSDocs.xslt<br \/>\n<\/font>&nbsp;&nbsp; oy.Load(ofs.GetFile(WScript.ScriptFullName).ParentFolder.ParentFolder &amp; _<br \/>\n<font color=\"#a31515\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;\\Deploy\\EditableResources\\xmlRSDocs.xslt&quot;<\/font>)<br \/>\n<font color=\"#0000ff\">End<\/font> <font color=\"#0000ff\">If<\/font> <br \/>\ntarget.Write(ox.TransformNode(oy))\n<\/p>\n<p>\nHowever, as the notes in the script make abundantly clear, I don&#39;t really recommend that particular TransformNode syntax, it&#39;s just the one I know most COM-XSLT people are used to seeing. As the notes show you, this approach is better:\n<\/p>\n<p style=\"color: #008000\" class=\"code\">\n&#39; processor = CREATEOBJECT(Msxml2.XSLTemplate&quot;)<br \/>\n&#39; styleSheet = CREATEOBJECT(&quot;Msxml2.FreeThreadedDOMDocument&quot;)<br \/>\n&#39; and use the following syntax:<br \/>\n&#39; styleSheet.Load(args.Item(1))<br \/>\n&#39; processor.styleSheet = styleSheet<br \/>\n&#39; now you can ask the processor for a compiled transform when you<br \/>\n&#39; need to process a source file, applying arguments specific to that<br \/>\n&#39; processing instance:<br \/>\n&#39; ox = CreateObject(&quot;Msxml2.FreeThreadedDOMDocument&quot;)<br \/>\n&#39; ox.Load(source) <br \/>\n&#39; oy = processor.CreateProcessor()<br \/>\n&#39; oy.AddParameter(&#8230;)<br \/>\n&#39; oy.input = ox<br \/>\n&#39; oy.Transform()<br \/>\n&#39; oy.output is your result&#8230;\n<\/p>\n<p>\nSo, really, no matter what coding environment and approach you choose, it is truly just a few lines of code.&nbsp; My java version doesn&#39;t look a heckuva lot different. VFP users can find pretty much the same lines of code you see in the comments above inside <a href=\"http:\/\/msdn2.microsoft.com\/en-us\/library\/ms953061(VS.80)\/\" target=\"_blank\" title=\"MSDN docs XMLListener\" rel=\"noopener\">the FFC XMLListener class<\/a>.&nbsp; XMLListener has all the necessary facilities in public methods so you can borrow it to transform any XML source, even if you aren&#39;t doing reporting.\n<\/p>\n<p>\nYour COM, or ASP.NET, or WinForm environment&nbsp;gets some choices from the user, and it&nbsp;uses those choices to request the data from the report&nbsp;server.&nbsp; The data XML&nbsp;export it receives from&nbsp;RS has&nbsp;various calculations and data transformations taken care of, by the original RDL expressions and rules.&nbsp;XSLT gives your&nbsp;app&nbsp;the opportunity to apply those same user choices, plus any other conditions of interest. You can create&nbsp;the presentations of your users&#39; dreams, or&nbsp;re-format the&nbsp;XML&nbsp;to fit some other application&#39;s schema requirements.\n<\/p>\n<p>\nCheck&nbsp;this stuff out.&nbsp; You won&#39;t be sorry.&nbsp; And you won&#39;t be limited by whatever is exposed by the vendor-provided formatting and automagic du jour.\n<\/p>\n<p>\n&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When I&nbsp;posted&nbsp;about using XSLT to create customized Excel in SQL Server Reporting Services, starting from RS&#39;s XML Data format, I deliberately included a step that allowed&nbsp;the reader&nbsp;to automagically attach the XSLT to your Reporting Services process: Now attach your XSLT document to the report by putting its name in the Data Output tab of the<a class=\"more-link\" href=\"https:\/\/spacefold.com\/lisa\/2007\/10\/28\/after-you-learn-to-walk-you-can-run-a-postscript-to-the-qnd-xslt-walkthrough\/\">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":[5,10],"tags":[],"class_list":["post-165","post","type-post","status-publish","format-standard","hentry","category-reporting","category-xml-xslt"],"_links":{"self":[{"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/posts\/165","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=165"}],"version-history":[{"count":0,"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/posts\/165\/revisions"}],"wp:attachment":[{"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/media?parent=165"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/categories?post=165"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/tags?post=165"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}