I have some questions about an XML project that im working on that I'm feeling rather rough around the edges on...

Quick overview... I'm scraping a page and through xpath creating an xml document... In that xml document I'm loading an XSL to transform everything into 3 tables... due to the flow of the xml, the natural sort order is by the column 'name'

Ok, so each of these table headers have links that I would like to use to drive dynamic sorting

e.g.

?table=active&sort=date

obviously, when I click them they do nothing

so i did some googling and ran across this website:

http://www.contentwithstyle.co.uk/content/dynamic-tables-with-xslt

... i followed his logic by adding the params (named to the QS vars) to my default template and tried putting them in my xsl:sort tags for each 'table' and they do nothing... when i attempt to output the param value, its always empty

So, my question is, am i missing something? I have seen the xsl functions and cant help but wonder if this isnt all tied together somehow...

    in order to use xsl to transform xml and sort it, you need:
    a) the xsl attributes to select the sort method
    b) the xsl script that does the actual sorting based on these attributes
    c) a method of passing the attributes to teh xsl

    c) is where most people get hung up.

    if you're having the transformation run clientside, then usually you need to have the transformation run via javascript and use this to inject the attributes for sorting

    if the transformation is clientside, then use php to inject the attributes.

    if you're still stuck, then post some sample xml, the xsl, and whatever method you are using to combine them.

      thanks for the reply

      ive tried all sorts of stuff... xsl:script, xsl:msscript containing javascript to parse the url and return the sort var

      so i had something like:

      <xsl:variable name="sortBy" select="xslscript:qs()"/>
      <xsl:script language="javascript" implements-prefix="xslscript">
      <![CDATA[
      function qs()
      {
      ...javascript to return the value of $_GET['sort']...
      }
      ]]>
      </xsl:script>

      when I run it I get an expression evaluation error on the xsl:variable declartion

      id like for the transformation to be done clientside... as is, my parser just dumps an xml file... once i goto say: example.xml i was hoping that everything could be self contained to process the sorting within the XSL using javascript without having to use php to transform it all over again

        ok, clientside is fine, but you're going to need to write a html container with the javascript that loads the xml and xsl, and handles the variables before running the transform, I believe.

        I havent done teh searches myself, but look for help on the javascript commands:
        XSLTTransform( xsl, xml, parameters )
        and for ie: ActiveXObject( 'MSXML2.XSLTemplate' )
        with addParameter()
        and for ff, etc:
        XSLTProcessor
        with setParameter()

        that should get you going 🙂

          I think I follow...

          ill putz with it tonight and see if I can get it to work...

          this is one of those types of things that you can't believe isn't boiled down to a simple expandable tutorial online somewhere...

          thanks dan

            mebbe if i get the time i'll write a tutorial 😛 been thinking of starting a blog anyways.

              so im still gettin' errors

              <?php
              
              $sort='';
              $table='';
              
              if(isset($_GET['sort']) and ctype_alnum($_GET['sort']) and isset($_GET['table']) and ctype_alnum($_GET['table']))
              {
              	$sort = $_GET['sort'];
              	$table = $_GET['table'];
              }
              ?>
              
              <html>
              <head>
              <script type="text/javascript">
              function loadXMLDoc(fname)
              {
                var xmlDoc;
                // code for IE
                if (window.ActiveXObject)
                {
                  xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
                }
                // code for Mozilla, Firefox, Opera, etc.
                else if (document.implementation
                && document.implementation.createDocument)
                {
                  xmlDoc=document.implementation.createDocument("","",null);
                 }
                else
                {
                  alert('Your browser cannot handle this script');
                }
              xmlDoc.async=false;
              xmlDoc.load(fname);
              return(xmlDoc);
              }
              
              function displayResult()
              {
              xml=loadXMLDoc("pr.xml");
              xsl=loadXMLDoc("pr.xsl");
              // code for IE
              if (window.ActiveXObject)
                {
                  ex=xml.transformNode(xsl);
                  document.getElementById("example").innerHTML=ex;
                }
                // code for Mozilla, Firefox, Opera, etc.
                else if (document.implementation
                && document.implementation.createDocument)
                {
                  xsltProcessor=new XSLTProcessor();
                  xsltProcessor.importStylesheet(xsl);
              	xsltProcessor.setParameter("sort","<?php echo $sort; ?>","");
              	xsltProcessor.setParameter("table","<?php echo $table; ?>","");
                  resultDocument = xsltProcessor.transformToFragment(xml,document);
                  document.getElementById("example").appendChild(resultDocument);
                }
              }
              </script>
              </head>
              <body id="example" onLoad="displayResult()">
              </body>
              </html> 
              

              in my xsl:

              	<xsl:param name="sort" />
              	<xsl:param name="table" />
              	<xsl:sort select="$sort" />
              

              throws this error:

              Error during XSLT transformation: XSLT transformation failed.

                strike that... i was running it locally... no errors now, but when i clock my sort links nothing changes in the sort... wen i view source the parameters in the setparameter are set appropriately

                  well that leaves you down to the xsl itself.
                  you'll want to have it spit out a dection that lists off the parameter values for debugging to start with, then if they're all as expected, it'll be in the sorting guts of the xsl

                    btw, when I first tried to do this it took me a few days to find out how, and work out the kinks, but it's pretty damn hot when it works.

                    I have my latest project working all in js - when the links are clicked, they call js functions that pass the variables and restor it realtime - no page reloads. all teh data is in teh xml which is loaded once, and i just reapply the xsl with the new parameters, and plop it back into the page over the pre-existing display. I even worked pagination into it 🙂
                    I'd give you a look at the source code but i did it for work, so i don't own the code, and it's sitting behind some tight security so the outside world can't see it (it's for paid subscribers, a reporting suite) but it allows a set of data to be selected, and gets uses the js to pull the xml from a php script that pulls the data from mysql, and formats it into xml, then the xsl goes to work from there.

                      CoderDan;10917222 wrote:

                      well that leaves you down to the xsl itself.
                      you'll want to have it spit out a dection that lists off the parameter values for debugging to start with, then if they're all as expected, it'll be in the sorting guts of the xsl

                      I have my params declared aright at the top and when I try to use:

                      <xsl:value-of select="$sort"/>

                      in my xsl, it doesnt output anything

                        appears i had the setParameter params wrong... documentation is sketchy on this stuff

                        	xsltProcessor.setParameter(null,"sort","<?php echo $sort; ?>");
                        	xsltProcessor.setParameter(null,"table","<?php echo $table; ?>");
                        

                        so then my output:

                        <xsl:value-of select="$sort"/>
                        

                        works but when I try:

                        <xsl:sort select="$sort"/>
                        

                        nothing changes!! and i verified that the variable im passing for sort is an element name in the XML tree

                        arg

                          well, it appears you are only setting parameters for mozilla based browsers (firefox, etc) - are you viewing this in firefox, or are you using ie for some strange reason?

                          for firefox the parameter setting appears correct to me.

                          in case it helps, I have a working js function that looks a lil something like this:
                          (of course, this references some vars that aren't showing, and is completly js driven, but you should be able to get the gist of it)

                          function XSLTTransform ( the_xsl, the_xml, parameter_array )
                          {
                          	if ( window.ActiveXObject )
                          	{
                          		var XSLTCompiled = new ActiveXObject( 'MSXML2.XSLTemplate' );
                          		XSLTCompiled.stylesheet = the_xsl.documentElement;
                          		// create XSL-processor
                          		var XSLTProc = XSLTCompiled.createProcessor();
                          		XSLTProc.input = the_xml;
                          
                          	if ( parameter_array )
                          	{
                          		for ( var i in parameter_array )
                          		{
                          			XSLTProc.addParameter( i, parameter_array[i] );
                          		}
                          	}
                          
                          	XSLTProc.transform();
                          
                          	if ( actions_div )
                          	{
                          		content_holder.innerHTML = "<div id='actions'>" + actions_div.innerHTML + "</div>" + XSLTProc.output;
                          	}
                          	else
                          	{
                          		content_holder.innerHTML = XSLTProc.output;
                          	}
                          }
                          else if ( document.implementation && document.implementation.createDocument )
                          {
                          	XSLTProc = new XSLTProcessor();
                          	XSLTProc.importStylesheet( the_xsl );
                          
                          	if ( parameter_array )
                          	{
                          		for ( var i in parameter_array )
                          		{
                          			XSLTProc.setParameter( null, i, parameter_array[i] );
                          		}
                          	}
                          
                          	TransformDoc = XSLTProc.transformToFragment( the_xml, document );
                          
                          	clearContent ( );
                          
                          	if ( actions_div )
                          	{
                          		content_holder.appendChild( actions_div );
                          	}
                          	content_holder.appendChild( TransformDoc );
                          }
                          else
                          {
                          	window.alert( 'Browser does not support XSLT.' );
                          	return false;
                          }
                          }

                            the actual method of sorting I used was the following:
                            my xml basically provided a sort value for each entry

                            <datal>
                              <entry>
                                <field>
                                  <name>Amount</name>
                                  <value>$10.00</value>
                                  <sort>1000</sort>
                                </field>
                                <field>
                                  <name>Date</name>
                                  <value>19/4/08</value>
                                  <sort>20080419</sort>
                                </field>
                              </entry>
                              <entry>
                                <field>
                                  <name>Amount</name>
                                  <value>$25.45</value>
                                  <sort>2545</sort>
                                </field>
                                <field>
                                  <name>Date</name>
                                  <value>18/4/08</value>
                                  <sort>20080418</sort>
                                </field>
                              </entry>
                            </data>
                            

                            that should give you the idea - for string values I just replicated the string in lowercase.
                            then I had my sort value be the 'column' number, with a desc flag
                            then in the xsl that displayed it, something like this (not sure if it meshes with my example xml )

                            				<xsl:choose>
                            					<xsl:when test='$sort_desc'>
                            						<xsl:apply-templates select='Result'>
                            							<xsl:sort order='descending' select='Field[$sort_by]/Sort' data-type='number' />
                            						</xsl:apply-templates>
                            					</xsl:when>
                            					<xsl:otherwise>
                            						<xsl:apply-templates select='Result'>
                            							<xsl:sort order='ascending' select='field[$sort_by]/sort' data-type='number' />
                            						</xsl:apply-templates>
                            					</xsl:otherwise>
                            				</xsl:choose>
                            

                            not sure if that's enough to give you a grasp of it, if not I can probably post a full example, just it's a pain to redact it 😛

                              perhaps providing my code can help you help me a little further

                              here is the block of xsl that dumps one of my three tables:

                              <h2>Current Collections</h2>
                              <table cellspacing="0" cellpadding="2">
                              	<thead><xsl:call-template name="table_header"/></thead>
                              	<tbody>
                              		<xsl:for-each select="channel/item[collectionStatus='Active']">
                              			<xsl:call-template name="table_row"/>			
                              		</xsl:for-each>
                              	</tbody>
                              </table>
                              

                              i was attempting to set the sort right under the foreach

                              currently have 8 header values that i would like to sort by

                                KK, I'm at home now, so no code of my own to look at, but from memory I think you need to set up the template table_row to have a parameter, and pass the search parameter to it.

                                  well my parameters are declared at the top of my xsl so they should be considered global

                                    it's also "crashing" when i add an xsl:sort element within my table_row template... presumable i need to have that sort element right after that for-each... any other way seems to make it die

                                      dan when you get a moment... i tried putzing around with your when/choose implementation a bit last night and I couldnt seem to make it work

                                      perhaps you could review your code at the office and give me a little more insight (my apologies for the annoying redactions)