Search code examples
xmlxsltxsdxslt-3.0

XSLT ERROR: Static error in XPath expression supplied to xsl:evaluate: Undeclared variable in XPath expression


I'm tring to use a value in a specific tag as variable name. But while converting xml system gives Undeclared variable in XPath expression Exception.

My Xml file is

<request>
    <entityType>individual</entityType>
</request>

And Xslt file is

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:math="http://www.w3.org/2005/xpath-functions/math"
    exclude-result-prefixes="xs math"
    version="3.0">

    <xsl:param name="individual" static="yes" as="xs:string" select="'1'"/>
    <xsl:param name="legal" static="yes" as="xs:string" select="'2'"/>
 

    <xsl:template match="/*">
  
      <xsl:param name="entity" as="xs:string" select="concat('$',entityType)"/>     
        <xsl:variable name="input" as="xs:string">
            <xsl:evaluate xpath="$entity"/>
        </xsl:variable>
    
        <HTML><TITLE><xsl:value-of select="$input"/></TITLE></HTML>
    </xsl:template>
</xsl:stylesheet>

i expect the result as

<HTML><TITLE>1</TITLE></HTML>

But I get "Static error in XPath expression supplied to xsl:evaluate: Undeclared variable in XPath expression" message.


Solution

  • If you read https://www.w3.org/TR/xslt-30/#dynamic-xpath then you will find it clearly states "Variables declared in the stylesheet in xsl:variable or xsl:param elements are not in-scope within the target expression.". You will have to use xsl:with-param inside the xsl:evaluate and/or with-params on the xsl:evaluate to declare the parameters you need.

    <xsl:evaluate xpath="$entity" with-params="map{ QName('', 'individual') : $individual }"/>
    

    As pointed out in your comment, you want to map certain string color values to integer color values, that might be possible in XSLT 3 with a map e.g. with an input of

    <colors>
      <color>red</color>
      <color>green</color>
    </colors>
    

    and an XSLT 3.0 of e.g.

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      version="3.0"
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      exclude-result-prefixes="#all"
      expand-text="yes">
      
      <xsl:param name="color-map"
                 as="map(xs:string, xs:integer)"
                 select="map {
                          'red' : 1,
                          'green' : 2
                        }"/>
                        
      <xsl:template match="color">
        <xsl:copy>{$color-map(.)}</xsl:copy>
      </xsl:template>
    
      <xsl:mode on-no-match="shallow-copy"/>
      
    </xsl:stylesheet>
    

    you would get a result of e.g.

    <colors>
      <color>1</color>
      <color>2</color>
    </colors>
    

    Online fiddle example.