将带参数的XSLT文件转换为另一个XSLT文件

时间:2013-11-13 12:03:46

标签: java xml xslt xpath

这里我有一个XSLT文件,其中一些XPath值来自外部。例如,我有1个参数:

<xsl:param name="companyName" select="''"/>

还有一个元素:

    <xsl:element name="Promotions">
        <xsl:attribute name="CompanyName">
            <xsl:value-of select="$companyName"/>
        </xsl:attribute>
        <xsl:apply-templates/>
    </xsl:element>

现在,当我为abc输入值companyName时,我想生成一个新的XSL文件,其中包含

<xsl:attribute name="CompanyName">abc</xsl:attribute>

我怎么能这样做?请帮我。非常感谢你。

P / s:我使用Java。

*编辑<!EM> *

简而言之,这就是我想要的:

在源文件中:

<xsl:param name="companyName" select="''"/>
<xsl:template name="start">
    <xsl:element name="Promotions">
        <xsl:attribute name="CompanyName">
            <xsl:value-of select="$companyName"/>
        </xsl:attribute>
         <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

当我输入abc作为CompanyName的值,myStart输出文件中的start时:

<xsl:template match="myStart">
    <xsl:element name="Promotions">
        <xsl:attribute name="CompanyName">abc</xsl:attribute>
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

1 个答案:

答案 0 :(得分:0)

XSLT样式表是一个XML文档,这与涉及将XML转换为XML的任何其他问题没有什么不同。在这种情况下,您似乎希望保留大部分输入文件(即初始样式表)相同,但用固定值替换任何<xsl:value-of select="$companyName" />。这可以通过基于“身份模板”的常规方法来完成,以将所有输入复制到输出,除非被更具体的模板覆盖。在这种情况下,“更具体的模板”是与特定value-of元素匹配的模板。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <!-- treat whitespace the same as an XSLT processor would - ignore text nodes
       containing only whitespace, except within xsl:text -->
  <xsl:strip-space elements="*" />
  <xsl:preserve-space elements="xsl:text" />

  <xsl:output method="xml" indent="yes" />

  <!-- the parameter you describe in the question -->
  <xsl:param name="companyName" select="''"/>

  <!-- the identity template -->
  <xsl:template match="@*|node()">
    <xsl:copy><xsl:apply-templates select="@*|node()" /></xsl:copy>
  </xsl:template>

  <!-- handling for the specific value-of element -->
  <xsl:template match="xsl:value-of[@select = '$companyName']">
    <xsl:value-of select="$companyName" />
  </xsl:template>
</xsl:stylesheet>

最后一个模板的match表达式正在查找由美元符号后跟companyName组成的字符串,而不是此样式表中参数的值,而实际为select将参数值作为文本节点插入。

但是,如果不是尝试替换原始样式表中参数值使用的位置(例如,上面的内容会遗漏在值中使用值的任何地方),它可能会更强大。更复杂的表达式,例如concat($companyName, ' (company)')),您只需将参数的定义重新编写为variable

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="xml"/>

  <!-- the parameter you describe in the question -->
  <xsl:param name="companyName" select="''"/>

  <!-- the identity template -->
  <xsl:template match="@*|node()">
    <xsl:copy><xsl:apply-templates select="@*|node()" /></xsl:copy>
  </xsl:template>

  <!-- handling for the specific param element -->
  <xsl:template match="/xsl:stylesheet/xsl:param[@name = 'companyName']">
    <xsl:element name="xsl:variable">
      <xsl:attribute name="name">companyName</xsl:attribute>
      <xsl:value-of select="$companyName" />
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

这会转换输入样式表,例如

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:param name="companyName" select="''" />

  <xsl:template match="/">
    <xsl:element name="Promotions">
      <xsl:attribute name="CompanyName">
        <xsl:value-of select="$companyName"/>
      </xsl:attribute>
      <xsl:apply-templates/>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:variable name="companyName">abc</xsl:variable>

  <xsl:template match="/">
    <xsl:element name="Promotions">
      <xsl:attribute name="CompanyName">
        <xsl:value-of select="$companyName"/>
      </xsl:attribute>
      <xsl:apply-templates/>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

它提供完全相同的行为,但companyName现在是硬编码而不是参数化。我开始生成<xsl:variable name="...">value</xsl:variable>而不是<xsl:variable name="..." select="'value'" />,以允许value可能包含单引号字符(例如“Sainsbury's”) - 使用文本内容通常被认为效率较低它会生成一个额外的节点,但是当值包含单引号或双引号,或者甚至是同一个字符串中的两种类型时,它都可以应对。