2009-07-14 60 views
0

以下工作:XSLT:XSL:功能不会为我工作

<xsl:variable name="core" select="document('CoreMain_v1.4.0.xsd')" /> 
<xsl:variable name="AcRec" select="document('AcademicRecord_v1.3.0.xsd')" /> 

<xsl:template match="xs:element">  
    <xsl:variable name="prefix" select="substring-before(@type, ':')" /> 
    <xsl:variable name="name" select="substring-after(@type, ':')" /> 

    <xsl:choose> 
    <xsl:when test="$prefix = 'AcRec'">    
     <xsl:apply-templates select="$AcRec//*[@name=$name]"> 
     <xsl:with-param name="prefix" select="$prefix" /> 
     </xsl:apply-templates>     
    </xsl:when> 
    <xsl:when test="$prefix = 'core'">    
     <xsl:apply-templates select="$core//*[@name=$name]"> 
     <xsl:with-param name="prefix" select="$prefix" /> 
     </xsl:apply-templates>     
    </xsl:when>    
    </xsl:choose> 
</xsl:template> 

但是我用同样的逻辑来处理基于前缀的电流或其他文档元素的查找,匹配节点名称在样式表中的许多地方。因此,改变样式表的版本到2.0后,我想:

<xsl:template match="xs:element"> 
    <xsl:value-of select="my:lookup(@type)" /> 
</xsl:template> 

<xsl:function name="my:lookup"> 
    <xsl:param name="attribute" /> 

    <!-- parse the attribute for the prefix & name values --> 
    <xsl:variable name="prefix" select="substring-before($attribute, ':')" /> 
    <xsl:variable name="name" select="substring-after($attribute, ':')" /> 

    <!-- Switch statement based on the prefix value --> 
    <xsl:choose> 
    <xsl:when test="$prefix = 'AcRec'">    
     <xsl:apply-templates select="$AcRec//*[@name=$name]"> 
     <xsl:with-param name="prefix" select="$prefix" /> 
     </xsl:apply-templates>     
    </xsl:when> 
    <xsl:when test="$prefix = 'core'">    
     <xsl:apply-templates select="$core//*[@name=$name]"> 
     <xsl:with-param name="prefix" select="$prefix" /> 
     </xsl:apply-templates>     
    </xsl:when>    
    </xsl:choose> 
</xsl:function> 

在我的阅读,我只发现返回文本的函数的例子 - 没有呼模板。我有一个印象,一个xsl:函数应该总是返回文本/输出...

经过更多的调查,它进入my:lookup函数和变量(前缀&名称)正在填充。所以它会输入xsl:choose语句,并且在测试时命中适当。问题似乎与apply-templates-value-of显示的是子值有关; copy-of也一样,我认为这很奇怪(不应该输出包含xml元素声明?)。如果将模板声明中的代码移动到xsl:function,为什么会有区别?

+0

哪个XSLT引擎?撒克逊或Xalan或其他什么?请注意,Xalan不支持XSLT 2.0,但Saxon不支持。 Xalan和Saxon都支持函数,但它们在XSLT 1.0和2.0之间的行为不同。 – lavinio 2009-07-14 18:43:33

+0

我正在使用撒克逊。 – 2009-07-14 19:02:51

回答

2

这已经有一段时间,因为我没有任何严重的XSLT,但IIRC你的问题是不是在功能,但在你的模板:

<xsl:template match="xs:element"> 
    <xsl:value-of select="my:lookup(@type)" /> 
</xsl:template> 

value-of语句不会内联结果树返回通过你的功能。相反,它会尝试将结果树减少为某种字符串,然后将其内联。这就是为什么你看到孩子的价值观,而不是自己的元素。

要内嵌函数返回的结果树,您需要使用一些模板将结果树复制到位。

所以,你的主模板将需要改变这样的:

<xsl:template match="xs:element"> 
    <xsl:apply-templates select="my:lookup(@type)" /> 
</xsl:template> 

,你会需要一些模板做递归调用。快速谷歌发现a good discussion of the identity template应该做你需要的。

(请原谅任何语法错误,正如我所说,它已经有一段时间...)