multiple Muenchian Grouping with sorting by parameter

I'm new to XML/XSLT and I've been dabbling abit in trying to this to work via html.  I have an XML (shown below), that I need to filter by year and then sort the results by section heading (it's not always indicative of date), and then sort within each section by date.

The filter by date uses a parameter passing that is selectable on the current webpage (which was posted by gertone on another posting) and currently it works fine - but when I try to do a subsequent grouping it duplicates the sections for each entry that exists in the section.

Any and all advise is welcome as I've been looking at this for awhile and using different muenchian combo's but I can't seem to get it to display in the desired formatting. The XLST listed doesn't contain a muenchian sort, as when I use it it's not displaying correctly.


desired output:

(clickable option to select year - 2010, 2009, 2008, etc)
If 2010 was selected, then it should display only records whose year matches 2010.

March 2010
  Stakeholders

February 2010
  February 2010 Newsletter
  February 2010 Internal Newsletter

January 2010
 Newsletter - Winter 2010
 
etc..

FYI : They years range from 2007-2010.

---------------------------
messages.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<root>
<Messages>
<record>
<section>MARCH, 2010</section>
<year>2010</year>
<date_posted>20100303</date_posted>
<file_description>Stakeholders</file_description>
<file_name>stakeholders.pdf</file_name>
<validity>OPEN</validity>
<new>NEW</new>
</record>
<record>
<section>FEBRUARY, 2010</section>
<year>2010</year>
<date_posted>20100205</date_posted>
<file_description>February 2010 Newsletter</file_description>
<file_name>newsFeb10-email.pdf</file_name>
<validity>OPEN</validity>
<new>OLD</new>
</record>
<record>
<section>FEBRUARY, 2010</section>
<year>2010</year>
<date_posted>20100202</date_posted>
<file_description>February 2010 Internal Newsletter</file_description>
<file_name>2010 February Newsletter.pdf</file_name>
<validity>OPEN</validity>
<new>OLD</new>
</record>
<record>
<section>JANUARY, 2010</section>
<year>2010</year>
<date_posted>20100110</date_posted>
<file_description>Newsletter - Winter 2010</file_description>
<file_name>Newsletter-Winter_2010.pdf</file_name>
<validity>OPEN</validity>
<new>OLD</new>
</record>
</Messages>
</root>

messages.xsl

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
    xmlns:map="internal" exclude-result-prefixes="map">
    <xsl:param name="extFilter" select="'2010'"/>
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
     <xsl:template match="Messages">
        <form>
            <xsl:for-each select="document('')//map:param/@name">
                <input type="radio" onclick="transformResult('{.}')" value="{.}" >
                    <xsl:if test=". = $extFilter">
                        <xsl:attribute name="checked">checked</xsl:attribute>
                    </xsl:if>
                    <xsl:value-of select="."/>
                </input><br /><br />
            </xsl:for-each>
        </form>
      <table width="730">
        <xsl:for-each select="record[year = $extFilter]">
            <xsl:value-of select="section"/>
          <table width="730" border="1">
               <tr>
             <td>
                 <A>      
                  <xsl:attribute name="href">
                    <xsl:value-of select="file_name" />
                  </xsl:attribute>    
                  <xsl:attribute name="target">_blank</xsl:attribute>
                  <xsl:value-of select="file_description"/>
                 </A>
             </td>
               </tr>
           </table>
        </xsl:for-each>
       </table>
    </xsl:template>
 <map:param name='2010'/>
 <map:param name='2009'/>
</xsl:stylesheet>

messages.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
     
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <script language="javascript">
         
      function transformResult(strFilter)
      {
         var oXML = new ActiveXObject("Msxml2.DOMDocument.4.0");
         var oXSL = new ActiveXObject("Msxml2.FreeThreadedDOMDocument.4.0");
         var oTmpl= new ActiveXObject("Msxml2.XSLTemplate.4.0");
         var oProc ;

             oXML.async = false;
         oXML.resolveExternals = false;
             oXML.load("messages.xml")        

         oXSL.async = false;
         oXSL.resolveExternals = false;
         oXSL.load("messages.xsl");

         oTmpl.stylesheet = oXSL;

         oProc = oTmpl.createProcessor();
         oProc.input = oXML;
         oProc.addParameter("extFilter", strFilter);
                         oProc.transform();
         var resHTM = oProc.output;
         document.getElementById('prod').innerHTML = resHTM;
      }
    </script>
</head>

<body onload="transformResult('2010');">
      <div id="prod"></div>
</body>
</html>





Michael_Langlois_NWCCACAsked:
Who is Participating?
 
Geert BormansConnect With a Mentor Information ArchitectCommented:
I think this is what you are looking for
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
    xmlns:map="internal" exclude-result-prefixes="map">
    <xsl:param name="extFilter" select="'2010'"/>
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:key name="sect" match="record" use="concat(year, section)"/>
    <xsl:template match="Messages">
        <form>
            <xsl:for-each select="document('')//map:param/@name">
                <input type="radio" onclick="transformResult('{.}')" value="{.}" >
                    <xsl:if test=". = $extFilter">
                        <xsl:attribute name="checked">checked</xsl:attribute>
                    </xsl:if>
                    <xsl:value-of select="."/>
                </input><br /><br />
            </xsl:for-each>
        </form>
        <table width="730">
            <xsl:for-each select="record[generate-id() = generate-id(key('sect',concat($extFilter, section))[1])]">
                <xsl:value-of select="section"/>
                <table width="730" border="1">
                    <xsl:for-each select="key('sect',concat($extFilter, section))">
                        <tr>
                            <td>
                                <A>      
                                    <xsl:attribute name="href">
                                        <xsl:value-of select="file_name" />
                                    </xsl:attribute>     
                                    <xsl:attribute name="target">_blank</xsl:attribute>
                                    <xsl:value-of select="file_description"/>
                                </A>
                            </td>
                        </tr>
                    </xsl:for-each>
                </table>
            </xsl:for-each>
        </table>
    </xsl:template>
    <map:param name='2010'/>
    <map:param name='2009'/>
</xsl:stylesheet>

Open in new window

0
 
Michael_Langlois_NWCCACAuthor Commented:
Thanks for the help gertone!!!  That was exactly what I was looking for and it makes perfect sense now that I can see it laid out for me.
0
 
Geert BormansInformation ArchitectCommented:
welcome,

I have a side comment
I see that you use a lookup table for generating the radio buttons.
That gives you full control over the radio buttons,
But, I would recommend using muenchian for generating the radio buttons.
That way the radio buttons only contain "years" that are available in the data,
and it is guaranteed that all available years are there.
It sounds a lot more flexible if you did it that way (or I could do it for you)
Then you don't always have to change the XSLT when a new year comes around
0
[Webinar] Kill tickets & tabs using PowerShell

Are you tired of cycling through the same browser tabs everyday to close the same repetitive tickets? In this webinar JumpCloud will show how you can leverage RESTful APIs to build your own PowerShell modules to kill tickets & tabs using the PowerShell command Invoke-RestMethod.

 
Michael_Langlois_NWCCACAuthor Commented:
That sounds ideal - I actually modified the structure of the xml abit and am using the <year> field in my xml as button references (for testing purposes, i'm going to change the <year> field into <category> or something), and there are a few non-year references in there...

<year>Internal news</year>
....
<year>Links</year>
etc...

I'd love to have it so that it would only display what's available in the present data for the <year> tag. I was thinking of this actually before you responded - but was stumped on the grouping aspect of it all.

I don't mind attempting it myself, but I'm still new to the grouping aspects of xml and muenchian and odds are it might be abit beyond me at this point. If you could show me the code, maybe with a brief explanantion so that I might be able to understand it better (especially the filter/muenchian combos), that'd be great.

0
 
Geert BormansInformation ArchitectCommented:
OK, will do for you and explain it properly

have you ever read Jeni Tennissons explanation of Muenchian?
highly recommended reading
http://www.jenitennison.com/xslt/grouping/muenchian.xml

can you send me the new XML, as soon as it is ready?
then I can make your XSLT based on the new XML
0
 
Michael_Langlois_NWCCACAuthor Commented:
Here's the revised xml structure (messages.xml):

<?xml version="1.0" encoding="ISO-8859-1"?>
<root>
<Messages>
<record>
<section>MARCH, 2010</section>
<category>2010</category>
<date_posted>20100303</date_posted>
<file_description>Stakeholders</file_description>
<file_name>stakeholders.pdf</file_name>
<validity>OPEN</validity>
<new>NEW</new>
</record>
<record>
<section>FEBRUARY, 2010</section>
<category>2010</category>
<date_posted>20100205</date_posted>
<file_description>February 2010 Newsletter</file_description>
<file_name>newsFeb10-email.pdf</file_name>
<validity>OPEN</validity>
<new>OLD</new>
</record>
<record>
<section>FEBRUARY, 2010</section>
<category>2010</category>
<date_posted>20100202</date_posted>
<file_description>February 2010 Internal Newsletter</file_description>
<file_name>2010 February Newsletter.pdf</file_name>
<validity>OPEN</validity>
<new>OLD</new>
</record>
<record>
<section>JANUARY, 2010</section>
<category>2010</category>
<date_posted>20100110</date_posted>
<file_description>Newsletter - Winter 2010</file_description>
<file_name>Newsletter-Winter_2010.pdf</file_name>
<validity>OPEN</validity>
<new>OLD</new>
</record>
<record>
<section>Other News</section>
<category>Other News</category>
<date_posted>20100331</date_posted>
<file_description>letter from the CEO</file_description>
<file_name>2010_03_letter.pdf</file_name>
<validity>OPEN</validity>
<new>OLD</new>
</record>
<record>
<section>Links</section>
<category>Links</category>
<date_posted>20090731</date_posted>
<file_description>internat</file_description>
<file_name>http://intranet/</file_name>
<validity>OPEN</validity>
<new>OLD</new>
</record>
</Messages>
</root>

Thanks in advance!!
0
 
Geert BormansInformation ArchitectCommented:
here you go
<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" 
    xmlns:map="internal" exclude-result-prefixes="map"> 
    <xsl:param name="extFilter" select="'2010'"/> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
    <xsl:key name="year" match="record[string-length(normalize-space(translate(category,'0123456789', ''))) = 0]" use="category"/>
    <xsl:key name="sect" match="record" use="concat(category, section)"/> 
    <xsl:template match="Messages"> 
        <form> 
            <xsl:for-each select="record[generate-id() = generate-id(key('year', category)[1])]"> 
                <input type="radio" onclick="transformResult('{category}')" value="{category}" > 
                    <xsl:if test="category = $extFilter"> 
                        <xsl:attribute name="checked">checked</xsl:attribute> 
                    </xsl:if> 
                    <xsl:value-of select="category"/> 
                </input><br /><br /> 
            </xsl:for-each> 
        </form> 
        <table width="730"> 
            <xsl:for-each select="record[generate-id() = generate-id(key('sect',concat($extFilter, section))[1])]"> 
                <xsl:value-of select="section"/> 
                <table width="730" border="1"> 
                    <xsl:for-each select="key('sect',concat($extFilter, section))"> 
                        <tr> 
                            <td> 
                                <A>       
                                    <xsl:attribute name="href"> 
                                        <xsl:value-of select="file_name" /> 
                                    </xsl:attribute>      
                                    <xsl:attribute name="target">_blank</xsl:attribute> 
                                    <xsl:value-of select="file_description"/> 
                                </A> 
                            </td> 
                        </tr> 
                    </xsl:for-each> 
                </table> 
            </xsl:for-each> 
        </table> 
    </xsl:template> 
</xsl:stylesheet>

Open in new window

0
 
Geert BormansInformation ArchitectCommented:
If you replace this
"record[string-length(normalize-space(translate(category,'0123456789', ''))) = 0]"
in the key for 'year'
with "record"
you will also get a radio button for "Other News" etc.

I just force it to only have radio buttons for years,
by demanding that the stringlength of the category is 0 after removing all digits
0
All Courses

From novice to tech pro — start learning today.