Hi I have a following xslt code :
<xsl:template match="table_terms_and_abbr">
<informaltable frame='none' colsep='none' rowsep='none'>
<tgroup cols='2' align='left'>
<colspec colnum="1" colwidth='1*'/>
<colspec colnum="2" colwidth='1*'/>
<xsl:apply-templates/>
</tgroup>
</informaltable>
</xsl:template>
and the following xml that it's processing :
<table_terms_and_abbr>
<tblrow_hdr>Name ,, Description</tblrow_hdr>
<tbody>
<tblrow_bold_first> BOT ,, &j_bot;</tblrow_bold_first>
...
</tbody>
</table_terms_and_abbr>
Now i want to improve the xslt by moving following lines inside the table_terms_and_abbr:
<tblrow_hdr>Name ,, Description</tblrow_hdr>
<tbody>
</tbody>
So i will have something like :
<xsl:template match="table_terms_and_abbr">
<informaltable frame='none' colsep='none' rowsep='none'>
<tgroup cols='2' align='left'>
<colspec colnum="1" colwidth='1*'/>
<colspec colnum="2" colwidth='1*'/>
<xsl:call-template name="tblrow_hdr">
BOT ,, &j_bot; * ???? *
</xsl:call-template>
<tbody>
<xsl:apply-templates/>
</tbody>
</tgroup>
</informaltable>
</xsl:template>
The line marked with * ???? * does not work. I using saxon9 (xslt 2.0 stylesheet) on linux platform and got this error:
XTSE0010: No character data is allowed within xsl:call-template
I know how to pass the attributes to the template i.e:
<xsl:with-param name="is_make_first_bold" select = "1" as="xs:integer"/>
but how to pass free text ?
The idea is move to the template all static data and in xml only use variable data i.e
<table_terms_and_abbr>
<tblrow_bold_first> BOT ,, &j_bot;</tblrow_bold_first>
...
</table_terms_and_abbr>
More Info
My requirement was to create a simplified syntax for defining repeatable tables for our DocBook documentation. For that i created a general named template tblrow that will split the line delimited by ",," to separate entities and will create a list of entries in the table row.
Each entry can be a simple string, an ENTITY or another template.
Since the parameter numbers are undefined (the tables can have different number of cells) i can't use a standard parameters for the templates and used delimited string. If i want to have one of the table entries to contain a link to some place in the document i can't use the parameters again since i can't pass xref template as a parameter.
The main reason not to change the tblrow template is that it's working :) and it's kind of complex. It's took me ages to achieve this and I'm not completely understand how it's working :).
Now on top of this i have a few variables that can control the displayed output like tblrow_hdr that will underline and bold the text in each entry. Since tblrow_hdr is common for all table_terms_and_abbr tables it just sounds logical to me not having this in xml rather put the call to the tblrow_hdr inside the table_terms_and_abbr template and here i stuck.
-
I know how to pass the attributes to the template i.e:
<xsl:with-param name="is_make_first_bold" select = "1" as="xs:integer"/>but how to pass free text ?
Pass the text as the content of an
xsl:with-paramelement.XSL Transformations 11.6 Passing Parameters to Templates
<xsl:with-param name = qname select = expression> <!-- Content: template --> </xsl:with-param>Parameters are passed to templates using the
xsl:with-paramelement. The requirednameattribute specifies the name of the parameter (the variable the value of whose binding is to be replaced). The value of the name attribute is a QName, which is expanded as described in [2.4 Qualified Names]. 'xsl:with-param' is allowed within bothxsl:call-templateandxsl:apply-templates. The value of the parameter is specified in the same way as forxsl:variableandxsl:param. The current node and current node list used for computing the value specified byxsl:with-paramelement is the same as that used for thexsl:apply-templatesorxsl:call-templateelement within which it occurs. It is not an error to pass a parameter x to a template that does not have anxsl:paramelement for x; the parameter is simply ignored.This example defines a named template for a numbered-block with an argument to control the format of the number.
<xsl:template name="numbered-block"> <xsl:param name="format">1. </xsl:param> <fo:block> <xsl:number format="{$format}"/> <xsl:apply-templates/> </fo:block><xsl:template match="ol//ol/li"> <xsl:call-template name="numbered-block"> <xsl:with-param name="format">a. </xsl:with-param> </xsl:call-template> </xsl:template>Ilya : so i will need to change the tblrow_bold_first template to receive parameter? I would like to avoid this. In the worst case i will not optimize and will repeat the lines in xml.ddaa : Either you include the text in the template, or you pass it in the template as a parameter, or you format it from the source document. I do not know what you want to do, just answering the specific technical questions.Ilya : i will try to add more info in the question. -
You can pass the additional string data as a parameter:
<xsl:with-param name="pNeededText" select="'--123Abc'"/>
and in the called template define this parameter:
<xsl:param name="pNeededText" as="xs:string">
Or, you could define a global
<xsl:variable/>or<xsl:param/>and reference it directly in the called template. -
> Since the parameter numbers are > undefined (the tables can have > different number of cells) i can't use > a standard parameters for the > templates and used delimited string.
Actually, this is not so. Here is an example of an<xsl:with-param/>
, the body of which is a node-set that may consist of different number of elements on different calls:<xsl:template match="/"> <xsl:variable name="vrtfTParams"> <p>xxx</p> <p>yyy</p> <p>zzz</p> </xsl:variable> <xsl:call-template name="makeTable"> <xsl:with-param name="pTParams" select="msxsl:node-set($vrtfTParams)/*"/> </xsl:call-template> </xsl:template>The "makeTable" template can be as simple as this:
<xsl:template name="makeTable"> <xsl:param name="pTParams"/> <table> <tr> <xsl:for-each select="$pTParams"> <td> <xsl:value-of select="."/> </td> </xsl:for-each> </tr> </table> </xsl:template>The msxsl:node-set() extension function can be used with a Microsoft XSLT processor. Most other processors support the exslt:node-set() extension function (Microsoft's .Net XSLT processor XslCompiledTransform also supports it).
In case the contents of $vrtfTParams is not dynamically generated (as is the case in this example), no xxx:node-set() function is necessary, because the contents of the <xsl:variable> can be passed like this:
<xsl:with-param name="pTParams" select="document('')/*/xsl:variable[name()=vrtfTParams)/*"/>Here $vrtfTParams must be globally defined (a child of <xsl:template/>).
In XSLT 2.0 (and XPath 2.0) there is no RTF type and no xxx:node-set() extension function is needed at all.
Hope this helped.
Cheers,
Dimitre Novatchev
Ilya : it's not clear to me how should look the xml that will be processed ? Currently the row in the table looks like this in xml :cell1 ,, &cell2 ,, and will create the corresponding table elements for each cell.Dimitre Novatchev : Ask another question about this. There is a standard XPath 2.0 tokenize() function. In XSLT 1.0 one can write a recursive template or use FXSL's str-split-to-words template. As I said, this is a totally different question and probably this was your main question in the first place.
0 comments:
Post a Comment