2

我正在尝试将常量折叠应用于简单数字表达式的 XML 表示。常量折叠是将常量(子)表达式替换为其文字值的过程。常量折叠的一部分是用计算的文字结果替换应用于两个文字值的每个二进制操作。所以说我们有一个表达式:

1+x+2*(3+1)

及其 XML 表示:

<addition>
   <addition>
      <value>1</value>
      <variable>x</variable>
   </addition>
   <multiplication>
      <value>2</value>
      <addition>
         <value>3</value>
         <value>1</value>
      </addition>
   </multiplication>
</addition>

我们可以替换

<addition>
   <value>3</value>
   <value>1</value>
</addition>

<value>4</value>

随后我们可以替换

<multiplication>
   <value>2</value>
   <value>4</value>
</multiplication>

<value>8</value>

最终结果应该是这样的(可以进一步简化,但现在就足够了):

<addition>
   <addition>
      <value>1</value>
      <variable>x</variable>
   </addition>
   <value>8</value>
</addition>

我的 XSLT 样式表的一部分如下所示:

<xsl:template match="addition[count(value) = 2]">
   <value>
      <xsl:value-of select="value[1] + value[2]" />
   </value>
</xsl:template>

<xsl:template match="multiplication[count(value) = 2]">
   <value>
      <xsl:value-of select="value[1] * value[2]" />
   </value>
</xsl:template>

...

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

这个模板的想法是递归地用包含计算值的单个值元素替换所有操作元素(加法,乘法,...),其中两个操作数(子)都是值元素。树的其余部分(包含变量的操作)将保持不变。

然而,这个样式表只会应用一次常量折叠,只会用它们的字面值替换最深的二元操作元素。我可以让这个样式表工作的唯一方法是继续转换最后一次转换的输出,直到输入和输出文档相同。我是 XSLT 的新手,所以我很确定应该有一种更自然的方法来做到这一点。

4

1 回答 1

2

这种转变

<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:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="addition[not(descendant::variable)]">
     <xsl:variable name="vArg1">
       <xsl:apply-templates select="*[1]"/>
     </xsl:variable>
     <xsl:variable name="vArg2">
       <xsl:apply-templates select="*[2]"/>
     </xsl:variable>

     <value>
       <xsl:value-of select="$vArg1 + $vArg2"/>
  </value>
 </xsl:template>

 <xsl:template match="multiplication[not(descendant::variable)]">
     <xsl:variable name="vArg1">
       <xsl:apply-templates select="*[1]"/>
     </xsl:variable>
     <xsl:variable name="vArg2">
       <xsl:apply-templates select="*[2]"/>
     </xsl:variable>

     <value>
       <xsl:value-of select="$vArg1 * $vArg2"/>
  </value>
 </xsl:template>
</xsl:stylesheet>

应用于提供的 XML 文档时

<addition>
   <addition>
      <value>1</value>
      <variable>x</variable>
   </addition>
   <multiplication>
      <value>2</value>
      <addition>
         <value>3</value>
         <value>1</value>
      </addition>
   </multiplication>
</addition>

产生想要的正确结果

<addition>
   <addition>
      <value>1</value>
      <variable>x</variable>
   </addition>
   <value>8</value>
</addition>

说明: 正确使用模板,xsl:apply-templates以及xsl:variable.

于 2011-12-28T15:59:56.983 回答