自动反转xsl

时间:2013-04-24 04:38:02

标签: xml xslt code-generation reverse inverse

让我们说我写了一个简单的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>

3 个答案:

答案 0 :(得分: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进行扩充。通过在“前进”和“后退”之间更改direction参数的值,可以来回切换转换方向。

答案 1 :(得分:1)

对于计算机科学专业的学生来说,确定是否有一类可逆的XSLT转换可能是一项有趣的练习。这当然意味着转型必须是无损的。最明显的候选者是除了重命名元素之外什么都不做的转换,但即便如此,我认为很难(不知道源文档的词汇和结构)来证明样式表没有将两个不同的输入名称映射到相同的输出名称。所以我认为这最终会成为一个相当小的集合。

在实践中,有用的人还可以考虑添加冗余信息的转换,例如HTML标头,以及两个输入元素映射到同一输出元素但具有不同属性的转换(比如div class =“X”) “其中X允许重构输入元素名称”。

答案 2 :(得分: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>