在 xslt 中应用连续转换

Applying consecutive transformations in xslt

我是 xslt 的新手,我有一个存储转换结果的变量 "name" 我们如何使用同一 xslt 文件中的其他模板转换变量 "name"。

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
  <xsl:strip-space elements="*" />
    <xsl:template match="@* | node()" >
      <xsl:variable name="name">
          <xsl:copy>
             <xsl:apply-templates select="@* | node()"/>
          </xsl:copy> 
      </xsl:variable>
   </xsl:template>
<xsl:template match="ns1:BP7Locations" >
    <xsl:copy>
      <xsl:apply-templates select="ns1:Entry">
        <xsl:sort select="ns4:Location/ns4:LocationNum" />
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

举个例子,你可以考虑这个XML:

<root>
<a>value</a>
</root>

还有这个 XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exslt="http://exslt.org/common" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="root">
    <xsl:variable name="a">
        <xsl:apply-templates select="a" mode="mode1"/>
    </xsl:variable>
    <xsl:apply-templates select="exslt:node-set($a)/a" mode="mode2"/>
</xsl:template>
<xsl:template match="a" mode="mode1">
    <a><xsl:value-of select="'mode1 called'"/></a>
</xsl:template>
<xsl:template match="a" mode="mode2">
    <a><xsl:value-of select="concat(., ' mode2 called')"/></a>
</xsl:template>
</xsl:stylesheet>

这将产生以下输出:

<?xml version="1.0" encoding="utf-8"?>
<a xmlns:exslt="http://exslt.org/common">mode1 called mode2 called</a>

XSLT 的第一个模板有一个变量 a,用于存储处理元素 <a> 后的数据,然后 xsl:apply-templates 再次处理变量 a 中的数据。这里 xsl:template 上的 @mode 区分第二个和第三个模板。

在 XSLT 2.0 中,多阶段转换的典型模式是

<xsl:variable name="temp1">
  <xsl:apply-templates mode="phase1"/>
</xsl:variable>
<xsl:variable name="temp2">
  <xsl:apply-templates select="$temp1" mode="phase2"/>
</xsl:variable>
<xsl:apply-templates select="$temp2" mode="phase3"/>

在 XSLT 1.0 中这是不允许的,因为该变量包含一个 "result tree fragment",它只能以非常有限的方式进行处理。几乎每个 XSLT 1.0 处理器都实现了 exslt:node-set() 扩展函数,因此您可以绕过这个限制。然后代码变为:

<xsl:variable name="temp1">
  <xsl:apply-templates mode="phase1"/>
</xsl:variable>
<xsl:variable name="temp2">
  <xsl:apply-templates select="exslt:node-set($temp1)" mode="phase2"/>
</xsl:variable>
<xsl:apply-templates select="exslt:node-set($temp2)" mode="phase3"/>

您需要将命名空间 xmlns:exslt="http://exslt.org/common" 添加到您的样式表。

你不必针对不同的处理阶段使用不同的模式,但它有助于避免难以发现的错误:每个处理阶段的模板规则应该有相应的模式属性,它也可以将每种模式的规则放在单独的样式表模块中是个好主意。