XSLT选择模板

本文关键字:选择 XSLT | 更新日期: 2023-09-27 18:18:24

我有一个用c#编写的应用程序,需要将模板名称应用于XSLT中定义的xml文件。

XML示例:

<Data>
    <Person>
        <Name>bob</Name>
        <Age>43</Age>
    </Person>
    <Thing>
       <Color>Red</Color>
    </Thing>
</Data>

XSLT例子:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:param name="TargetName" />
    <xsl:param name="RootPath" />
    <xsl:Template Name="AgeGrabber">
        <xsl:value-of select="/Person/Age" />
    </xsl:Template>
    <xsl:Template Name="ColorGrabber">
        <xsl:value-of select="/Color" />
    </xsl:Template>
</xsl:stylesheet>

假设我想运行路径为"/Data/Thing"的模板"ColorGrabber",然后运行路径为"/Data"的模板"AgeGrabber"的另一个转换。这可能吗?我想我可以传入路径和模板名称(加上顶部的2个参数),然后做一些类型的切换,但它看起来像xsl:call-template不能将参数作为名称属性。

我如何实现这个行为?

XSLT选择模板

这个问题有很多问题:

  1. <xsl:stylesheet version="2.0" ...是指定的,但是,目前>NET不支持XSLT 2.0。

  2. 代码示例不是太有意义,因为一个XML文档不能同时包含/Person/Age/Color元素——一个格式良好的XML文档只有一个顶部元素,它可以是PersonColor,但不能同时包含。

如果有一个更有意义的例子:

<Person>
 <Age>27</Age>
 <HairColor>blond</HairColor>
</Person>

一个简单的解决方案是:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:param name="pProperty" select="'Age'"/>
 <xsl:template match="/">
  <xsl:value-of select="/*/*[name()=$pProperty]"/>
 </xsl:template>
</xsl:stylesheet>

,当这个转换应用于上面的XML文档时,它会产生想要的结果:

27

如果感兴趣的元素的嵌套性可以是任意的,并且/或者我们需要对不同的元素做不同的处理,那么一个合适的解决方案是使用匹配模板(非命名模板):

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>
 <xsl:param name="pProperty" select="'HairColor'"/>
 <xsl:template match="Age">
  <xsl:if test="$pProperty = 'Age'">
    This person is <xsl:value-of select="."/> old.
  </xsl:if>
 </xsl:template>
 <xsl:template match="HairColor">
  <xsl:if test="$pProperty = 'HairColor'">
    This person has <xsl:value-of select="."/> hair.
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>

当将此转换应用于相同的XML文档(如上所述)时,将再次生成正确的结果:

This person has blond hair.

最后,如果您真的想在XSLT 1.0或XSLT 2.0中模拟高阶函数(HOF),请参阅以下答案:https://stackoverflow.com/a/8363249/36305,或者了解FXSL

更简单:准备两个应用模板规则(用于Age和Color元素),并有条件地发送适当的节点来转换-//Person/Age或//Thing/Color

你搞反了。您应该创建模板,匹配您想要使用的节点。

<xsl:stylesheet>
    <xsl:template match="Person|Thing">
        <xsl:apply-templates />
    </xsl:template>
    <xsl:template match="Person">
        <xsl:value-of select="Age" />
    </xsl:template>
    <xsl:template match="Thing">
        <xsl:value-of select="Color" />
    </xsl:template>
</xsl:stylesheet>