Search

i can't make it right

i have the a page where i'm calling a template, and i'm also passing it a filtering parameter.

<xsl:call-template name="snippet">
    <xsl:with-param name="snippet-name">about-us</xsl:with-param>
</xsl:call-template>

there goes the template

<xsl:template name="snippet" select="//snippets/entry/name[@handle = 'about-us']">
    <!-- return node data -->
</xsl:template>

the whole ideea is that by a passing parameter, a node content be returned by calling that template.

this is the xml data

  <snippets>
    <section id="12" handle="snippets">Snippets</section>
    <entry id="1">
      <name handle="about-us">About us</name>
      <content>snippet content</content>
    </entry>

    <entry id="2">
      <name handle="ga-code">Ga code</name>
      <content>google code</content>
    </entry>
  </snippets>

thank you

i'm in this point

i'm calling it this way

<xsl:call-template name="snippet">
    <xsl:with-param name="snippet-name" select="'about-us'"/>
</xsl:call-template>

and i have

<xsl:template name="snippet">
    <xsl:param name="snippet-name" />
    <xsl:param name="source" select='//snippets/entry'/>

    <xsl:for-each select="$source/name[@handle = $snippet-name]">
        <xsl:value-of select="content"/>
    </xsl:for-each>
</xsl:template>

the problem is i can't get the value of content based on name

  <snippets>
    <entry id="28">
      <name handle="about-us">About us</name>
      <content>content</content>
    </entry>
   </snippets>

any ideea how i can see it ?

thank you

As far as I can tell you just need to step back a node, so ../content rather than content

Hi, I presume you want to have a mean to namely call out prepared snippets. I would use a xsl:key for that (for kind of elegancy and performance I think too).

So, for the XML example above

<data>
....

<snippets>
    <section id="12" handle="snippets">Snippets</section>
    <entry id="1">
        <name handle="about-us">About us</name>
        <content>snippet content</content>
    </entry>

    <entry id="2">
        <name handle="ga-code">Ga code</name>
        <content>google code</content>
    </entry>
</snippets>

....
</data>    

you would define a xsl:key outside xsl:template like

...    
<!-- Snippets Key -->    
<xsl:key name="snippet" match="/data/snippets/entry" use="name"/>
...
...    
<xsl:template match="/">
...
...
</xsl:template>
...    

and in the template you could call it like key('snippet', 'snippet's full name here') so

...
<!-- 1. Return only text from the content -->
<xsl:value-of select="key('snippet', 'About us')/content"/>    
...
...
<!-- or 2. Return content text also with all the proper markup it may have -->
<xsl:copy-of select="key('snippet', 'Ga code')/content/node()"/>    

I guess the 2. way is more versatile.

At some point of consideration (I guess for more performance gains) I would use only system ids to identify the snippets, leaving out the names so I would have less XML traffic / parsing and still had a clue which id is which code from the backend. But thats off-topic for now.

Hope I helped a bit.

great! it works :d

Oh I wouldn't get keys involved in something as simple as this, there's too much overhead and complication for this scenario.

You almost had it right with your first attempt, it's just a matter of understanding the scope of your xslt nodes.

<xsl:call-template name="snippet">
    <xsl:with-param name="snippet-name">about-us</xsl:with-param>
</xsl:call-template>

<xsl:template name="snippet">
    <xsl:param name="snippet-name" />
    <xsl:param name="source" select='/data/snippets/entry'/>

    <xsl:for-each select="$source/[name/@handle = $snippet-name]">
        <xsl:value-of select="content/text()"/>
    </xsl:for-each>
</xsl:template>

As you can see above, I've changed the scope of your for-each select statement, and adjusted the predicate to say, any item in $source that has a name node with an @handle of $snippet-name. Doing it that way keeps you at the entry level in your scope, so any nodes you call within the for-each are at the entry level.

Then you can use the value-of select statement as you would expect.

All this being said, it would be much more efficient to use apply-templates as by calling a template and then initiating a for-each, this is what you're doing anyway but with one extra level of overhead.

<xsl:apply-templates select="/data/snippets/entry[name/@handle = 'about-us']" mode="snippet"/>

<xsl:template match="snippets/entry" mode="snippet">
    <xsl:value-of select="content/text()"/>
</xsl:template>

It's much simpler, cleaner, more efficient, less code...

it also works and if you're saying is more efficient, i am going to use it thank you both :)

you made me change the code twice :P haha

Thanks for this instruction designermonkey. I also had the apply-templates & mode way at the first place in mind, but went for the keys. Also, the given key could be written more specific, e.g. pointing directly to the content. But I can only favor the apply-templates.

About keys, I had (or have) a working idea, that keys are effective if you have a (large?) set of nodes to pick from, rather to store the whole node set in a variable for dedicated access, or you need to combine variety of data from different sources. But yes, all this can be generally omitted with the use of basic apply-templates, more over in common solutions.

Huh, I am still playing around with the xslt.

Create an account or sign in to comment.

Symphony • Open Source XSLT CMS

Server Requirements

  • PHP 5.3-5.6 or 7.0-7.3
  • PHP's LibXML module, with the XSLT extension enabled (--with-xsl)
  • MySQL 5.5 or above
  • An Apache or Litespeed webserver
  • Apache's mod_rewrite module or equivalent

Compatible Hosts

Sign in

Login details