2

假设我已经编写了一个简单的 xslt,它可以从一条消息转换为另一条消息,有什么方法可以自动生成逆吗?

原始 XSLT

 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
      <xsl:template match="/">
      <hello>
         <xsl:for-each select="/hello/greeting">        
        <H1>
              <xsl:value-of select="."/>
        </H1>
       </xsl:for-each>
       </hello>
      </xsl:template>
    </xsl:stylesheet>

所需的 XSLT

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:template match="/">
   <hello>
   <xsl:for-each select="/hello/H1">        
      <greeting>
          <xsl:value-of select="."/>
      </greeting>
   </xsl:for-each>
   </hello>
  </xsl:template>
</xsl:stylesheet>
4

3 回答 3

2

不,没有通用的方法来反转 XSLT。事实上,我想说大多数 XSLT 是不可逆的。但是,可以将上面的示例设计为可以通过更改参数值以正向或反向运行:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:exslt="http://exslt.org/common">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
  <xsl:param name="direction" select="'forward'" />

  <xsl:variable name="mappingNF">
    <map from="greeting" to="H1" />
    <map from="pleasantry" to="H2" />
  </xsl:variable>
  <xsl:variable name="mapping" select="exslt:node-set($mappingNF)" />

  <xsl:template match="@* | node()" priority="-1" name="Copy">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="*" mode="copy">
    <xsl:call-template name="Copy" />
  </xsl:template>

  <xsl:template match="*">
    <xsl:variable name="mappingItem"
                  select="$mapping/*[$direction = 'forward' and @from = local-name(current()) or
                                 $direction = 'reverse' and @to = local-name(current())]" />

    <xsl:apply-templates select="current()[$mappingItem]" mode="rename">
      <xsl:with-param name="mappingItem" select="$mappingItem" />
    </xsl:apply-templates>
    <xsl:apply-templates select="current()[not($mappingItem)]" mode="copy" />
  </xsl:template>

  <xsl:template match="*" mode="rename">
    <xsl:param name="mappingItem" />

    <xsl:element name="{$mappingItem/@to[$direction = 'forward'] |
                        $mappingItem/@from[$direction = 'reverse']}">
      <xsl:apply-templates select ="@* | node()" />
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

表示节点名称之间的mappingNF对应关系,并且可以根据需要增加任意map数量的 s。direction通过在“forward”和“reverse”之间改变参数的值,可以来回切换转换的方向。

于 2013-04-24T07:43:26.103 回答
1

对于计算机科学专业的学生来说,也许有一个有趣的练习来确定是否存在一类可逆的 XSLT 转换。这当然意味着转换必须是无损的。最明显的候选者是除了重命名元素之外什么都不做的转换,但即便如此,我认为证明样式表没有将两个不同的输入名称映射到相同的输出名称。所以我认为它最终会成为一个相当小的系列。

在实践中有用的人还需要考虑添加冗余信息的转换,例如 HTML 标头,以及两个输入元素映射到相同输出元素但具有不同属性的转换(比如 div class="X" where X使输入元素名称能够被重构)。

于 2013-04-24T08:25:38.297 回答
0

我认为没有一种方法可以自动生成反向

但是,如果模板的作用相同,您可以重用当前 XSL 中的大部分内容

在您的示例中,它将是

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:template match="/">
  <hello>
     <xsl:for-each select="/hello/H1 | /hello/greeting">       
    <H1>
          <xsl:value-of select="."/>
    </H1>
   </xsl:for-each>
   </hello>
  </xsl:template>
</xsl:stylesheet> 
于 2013-04-24T06:00:48.760 回答