Click here to Skip to main content
15,887,854 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
Hi,

I am using an XSL file to format a document for display on my website. A content block has a title, and contains HTML content. The references section always appears at the bottom of the rendered document (regardless of its location within the XML file).

<?xml version="1.0"?>
<mydoc>
   <content title="Introduction">
      ...
   </content>
   <references>
      ...
   </references>
</mydoc>

In the XSL I want to create a contents for the document. I have managed to get the content sections listed in the contents. But I find myself duplicating a large chunk of XSL just to add the references section to the contents.

Is there a way to do something along the lines of the following?

<xsl:variable name="contents-listing">
   concatenate
      ?? Get list of content nodes "/mydoc/content" ??
   with
      <content title="References">
         <references>
            ...
         </references>
      </content>
</xsl:variable>

so that I can:

<xsl:for-each select="$contents_listing">
   <!-- Clicking an item goes to the corresponding named anchor -->
   <a>
      <xsl:attribute name="href">
         <xsl:value-of select="concat('#ref', position())" />
      </xsl:attribute>
      <xsl:value-of select="@title" />
   </a>
</xsl:for-each>

and also:

<xsl:for-each select="$contents-listing">
   <!-- Named anchor indicates where to click goes to -->
   <a>
      <xsl:attribute name="name">
         <xsl:value-of select="concat('ref', position())" />
      </xsl:attribute>
      <xsl:apply-templates />
   </a>
</xsl:for-each>

Many thanks,
Lea Hayes
Posted

1 solution

It's probably easy in XSLT 2, but if you're using XSLT 1 like most of us who are relying on Microsoft tools, avoiding duplicated xsl code ist hard.

Using a workaround pattern I've sometimes applied in such cases it would look like this:

<mydoc>
   <content title="Introduction">
        
              <xsl:call-template name="EvaluateContent">
          <xsl:with-param name="Context">Contents</xsl:with-param>
     </xsl:call-template>
        
   </content>
   <references>
        
              <xsl:call-template name="EvaluateContent">
          <xsl:with-param name="Context">References</xsl:with-param>
     </xsl:call-template>
        
   </references>
</mydoc>

<xsl:template name="EvaluateContent">

     <xsl:param name="Context" />
    
     <xsl:for-each select="/mydoc/content">
    
          <xsl:choose>
              
               <xsl:when test="$Context = 'Contents'">
                   
                    <a>
                             <xsl:attribute name="href">
                         <xsl:value-of select="concat('#ref', position())" />
                             </xsl:attribute>
                             <xsl:value-of select="@title" />
                             </a>
  
               </xsl:when>
              
               <xsl:when test="$Context = 'References'">
                   
                    <a>
                             <xsl:attribute name="name">
                         <xsl:value-of select="concat('ref', position())" />
                             </xsl:attribute>
                    </a>
  
               </xsl:when>
              
          </xsl:choose>
    
     </xsl:for-each>

</xsl:template>    

This is not nice, and can be further refined, but the only way I know to avoid duplicating the logic contained in the for-each statement.

I don't have the patience right now to adjust the tabs and spaces which don't look right in the preview.

And please be aware that I just copied and pasted it from some old stylesheets of mine and your fragments and have not tested it. There may be syntax errors, but I'm sure you get the gist.

And if any one points out a better pattern, I'll add my thanks to yours.
 
Share this answer
 


CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900