能否对Map与Array结构使用apply-templates进行匹配转换?
XSLT中Map/Array无法直接使用
apply-templates的解决方案 apply-templates是XSLT专为XML节点设计的核心指令,默认确实不直接支持Map、Array这类XPath 3.0+引入的序列类型,你遇到的情况是正常的设计限制,以下是几种可行的适配方案:
1. 将Map/Array转换为临时XML节点集
把非节点结构转成XML节点序列,就能复用apply-templates的节点匹配逻辑:
<xsl:template match="/"> <!-- 示例数组变量 --> <xsl:variable name="demo-array" select="('apple', 'banana', 'cherry')"/> <!-- 转换为XML节点 --> <xsl:variable name="array-nodes"> <xsl:for-each select="$demo-array"> <fruit><xsl:value-of select="."/></fruit> </xsl:for-each> </xsl:variable> <!-- 正常使用apply-templates --> <xsl:apply-templates select="$array-nodes/fruit"/> </xsl:template> <xsl:template match="fruit"> <processed-fruit><xsl:value-of select="concat('Processed: ', upper-case(.))"/></processed-fruit> </xsl:template>
处理Map时,可遍历键值对生成节点:
<xsl:variable name="demo-map" select="map { 'id': '1001', 'name': 'Alice' }"/> <xsl:variable name="map-nodes"> <xsl:for-each select="map:keys($demo-map)"> <entry key="{.}"><xsl:value-of select="$demo-map(.)"/></entry> </xsl:for-each> </xsl:variable> <xsl:apply-templates select="$map-nodes/entry"/>
2. 用for-each结合模板调用替代
如果不想转换为XML节点,可直接遍历Map/Array,通过call-template传递元素进行处理:
<xsl:template match="/"> <xsl:variable name="demo-map" select="map { 'price': '29.99', 'stock': '50' }"/> <xsl:for-each select="$demo-map?*"> <xsl:call-template name="process-map-entry"> <xsl:with-param name="entry-value" select="."/> </xsl:call-template> </xsl:for-each> </xsl:template> <xsl:template name="process-map-entry"> <xsl:param name="entry-value"/> <formatted-entry><xsl:value-of select="concat('Formatted: ', format-number($entry-value, '#,##0.00'))"/></formatted-entry> </xsl:template>
3. 利用XSLT 3.0模式扩展(需支持的处理器如Saxon)
部分XSLT 3.0处理器允许扩展模式来匹配原子值,可直接对Array元素应用模板:
<!-- 定义自定义模式 --> <xsl:mode name="process-array" on-no-match="shallow-copy"/> <!-- 匹配字符串类型的数组元素 --> <xsl:template match="xs:string" mode="process-array"> <array-item><xsl:value-of select="concat('Uppercase: ', upper-case(.))"/></array-item> </xsl:template> <xsl:template match="/"> <xsl:variable name="demo-array" select="('red', 'green', 'blue')"/> <!-- 对数组元素应用指定模式的模板 --> <xsl:apply-templates select="$demo-array" mode="process-array"/> </xsl:template>
内容的提问来源于stack exchange,提问作者MrD at KookerellaLtd
相关产品推荐
相关产品推荐

