hbi99 / defiant.js

http://defiantjs.com
GNU Affero General Public License v3.0
913 stars 91 forks source link

NodeJS: registering multiple templates is not possible #108

Closed gtamas closed 5 years ago

gtamas commented 5 years ago

Hi

The NodeJS API works nicely, but it seems it's not possible to register more than one XSL template at a time. This is fine as long as you don't wanna do something like this:

<xsl:template name="tree">
    <h1>Tree</h1>
    <xsl:call-template name="tree-walker"/>
</xsl:template>

<xsl:template name="tree-walker">
    <xsl:param name="indent" />
    <xsl:for-each select="./*">
        <xsl:sort order="descending" select="count(./*)"/>
        <div class="tree-item">
            <xsl:value-of select="$indent"/> <xsl:value-of select="@name"/>
            <xsl:if test="count(./*) > 0">
                <div class="item-children">
                    <xsl:call-template name="tree-walker">
                        <xsl:with-param name="indent">
                            <xsl:value-of select="$indent"/>&#160;&#160;
                        </xsl:with-param>
                    </xsl:call-template>
                </div>
            </xsl:if>
        </div>
    </xsl:for-each>
</xsl:template>

You cannot register both of these templates, therefore this won't work.

Would it be possible to add multiple template support in the future? For example, it could register templates by name (after all, rendering already requires a name).

Or am I doing something wrong here?

hbi99 commented 5 years ago

@gtamas It is possible to register multiple templates the same way you have exemplified. This is why you declare the name of the template you want to be used when calling the method render. I started back in 2006 to declare all my templates together and I never looked back. On of the advantages is that you can call templates if they are available in execution context, as well as making recursive calls.

This is for instance what I'm doing with rebellious - I collect all the templates and register them at the same time. Using chokidar, I listen to changes to XSL files and re-register them on file updates. Now, some do declare the attribute "match" attribute with the xsl:template node but there should not be such in my option. The match attribute is set by the render method.

The templates above as is, is not a valid XSL code unless it s wrapped like this:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <!-- templates goes here -->
</xsl:stylesheet>

In defiant.js, I do declare one extra namespace - but that is due to internal works related to JSON being the source and transformations that comes with it.

...so, you should register all your templates at the same time. Best approach is to have them in one single file - or at least have in separate files but include them in a "master xsl file" and register that one.