views:

32

answers:

2

I'd like to do something like "Hello %s" and have "World" in another variable.

Of course I could do this simple case using string replacement but if possible I'd like all sprintf() features like argument reordering, which would be very complex to do myself.

+1  A: 

If you are performing the transform inside a language that supports extending XSLT using an extension object (such as one of the .NET languages or PHP); then you can simply create a function to do this and call it from within your XSLT.

Tim
Yes, I'm using XSLT from PHP. Can you please give me an example or link to something similiar like I want to do?
http://www.php.net/manual/en/xsltprocessor.registerphpfunctions.php
Tim
Thanks a lot, this is exactly what I was looking for and the project I'm working on actually uses this approach already.I'm still thinking of the best approach to pass a variable number of variables to XSLT. These would be the arguments to sprintf(). vsprintf() is also an option if an array would be easier.
+1  A: 

The XML/XSLT equivalent of Hello World is this:

We have this XML document:

<t>Hello <rep/>!</t>

and use this transformation on it:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="rep">
  <xsl:value-of select="'World'"/>
 </xsl:template>
</xsl:stylesheet>

The wanted result is produced:

<t>Hello World!</t>

Do note:

  1. We use and override the identity rule. This is the most fundamental XSLT design pattern.

  2. We can intersperse a constant content with many different replacement elements and thus have a "fill-in the blanks" technique.

  3. Using this technique a full separation between content and processing logic can be achieved. The XSLT code doesn't know what source XML document it is processing (the document URL can even be passed as parameter). The same XSLT stylesheet can be used any fill-in the blanks document and any fill-in the blanks document can be processed by different XSLT stylesheets. This separation achieves maximum flexibility and maintainability.

  4. If you only want just text to be produced, this can also be done easily -- for example using <xsl:output method="text"/>

Dimitre Novatchev
@Dimitre: +1 for a good answer that does not invoque extension functions. Also this could be done just with: `concat('Hello ',$s)`
Alejandro
@Alejandro: Thanks for your appreciation! BTW, do have a look at the chat...
Dimitre Novatchev
It took me a while to realize how this solves my problem :) But it does, by "naming" arguments (<rep1/> <rep2/>) I can easily reorder them in the format strings. And thanks for all the notes, too, I do not yet understand them completely but soon I will! :) I'm glad to know both approaches (pure XSLT and extension objects).
Hmm, it seems like only one answer can be flagged as accepted. But both approaches solve my problem.
@helix84: Don't worry, Only one answer can be accepted, but many answers can be up-voted and they get +10 reputation points (an accepted answer gets +15). You will be able to up-vote once you yourself have accumulated 50 rep. points (I think). Then you would be able to both accept and up-vote answers.
Dimitre Novatchev