Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use a function from one xsl in another

Tags:

xslt

I have two xsl files: "one.xsl" and "two.xsl"

one.xsl:

 <xsl:function name="x:trans" as="xs:string">
    <xsl:param name="str"></xsl:param>
    <xsl:variable name="res1" select="x:translate_string($str)"/>
    <xsl:sequence select="$res1"/> 
</xsl:function>
</xsl:stylesheet>

I want to use function "x:trans" in "one.xsl"

How do i reference the function to another file?


The problem is that when i try to call for this function this way:

< xsl:value-of select="x:trans('Hello World')"/>

I get the following error message from browser:

Reference to undeclared namespace prefix: 'x'

like image 836
Michael Avatar asked Aug 22 '10 10:08

Michael


Video Answer


3 Answers

Apart from the correct replies that you need to <xsl:include> or <xsl:import> (I'd recommend the latter as the former can often result in duplication errors), your other problem is the following:

  1. A function name must belong to a namespace.

  2. The namespace must be declared (defined and bound to a prefix) in the same file in which the function is defined.

  3. Any call to the function has to prefix the name of the function and that prefix must be bound to the same namespace to which the function name belongs

Here is a simple example:

I. File deleteA.xsl defines the function my:double

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:my="my:my"
    >
 <xsl:function name="my:double" as="xs:double">
  <xsl:param name="pArg" as="xs:double"/>

  <xsl:sequence select="2*$pArg"/>
 </xsl:function>
</xsl:stylesheet>

II. File deleteB.xsl imports file deleteA.xsl and uses the function my:double :

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:my="my:my">
    <xsl:import href="deleteA.xsl"/>

    <xsl:output method="text"/>

    <xsl:template match="/">
      <xsl:sequence select="my:double(.)"/>
    </xsl:template>
</xsl:stylesheet>

III. The transformation contained in deleteB.xsl is applied on the following XML document:

<t>1</t>

and the correct result is produced:

2

Additional comment: At present no browser supports XSLT 2.0 transformations -- xsl:function is only available in XSLT 2.0 +.

like image 91
Dimitre Novatchev Avatar answered Sep 20 '22 22:09

Dimitre Novatchev


You want to either do <xsl:include /> or <xsl:import />. <xsl:include /> is simpler (it just drags everything in) while <xsl:import /> is more flexible (if there are templates colliding between the two, the over-ride of the called by the calling is better defined and generally sensible).

Edit for added info:

You need to make sure you call the templates in the imported stylesheet using the appopriate namespace. The easiest way is to make sure you have matching xmlns:foo declarations in the stylesheets, though you could call foo:template in one stylesheet as bar:template in the other if it had xmlns:bar instead.

like image 32
Jon Hanna Avatar answered Sep 18 '22 22:09

Jon Hanna


In two.xsl:

<xsl:include href="one.xsl" />

Also see the description of include in the XSLT 2.0 spec.

like image 35
Tomalak Avatar answered Sep 19 '22 22:09

Tomalak