如何使用可选值在XSLT中模拟C枚举

Roa*_*alt 5 c xslt

我正在尝试进行生成C代码的XSLT转换,应转换以下XML:

<enum name="anenum">
  <enumValue name="a"/>
  <enumValue name="b"/>
  <enumValue name="c" data="10"/>
  <enumValue name="d" />
  <enumValue name="e" />
</enum>
Run Code Online (Sandbox Code Playgroud)

它应转换为以下C代码:

enum anenum {
   a = 0,
   b = 1,
   c = 10,
   d = 11,
   e = 12
}
Run Code Online (Sandbox Code Playgroud)

或替代(因为C预处理器将处理求和):

   enum anenum {
       a = 0,
       b = 1,
       c = 10,
       d = c+1,
       e = c+2
    }
Run Code Online (Sandbox Code Playgroud)

我的XSLT的核心看起来像:

<xsl:for-each select="enumValue">
  <xsl:value-of select="name"/>
  <xsl:text> = </xsl:text>
  <xsl:choose>
    <xsl:when test="string-length(@data)&gt;0">
      <xsl:value-of select="@data"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="position()-1"/>
    </xsl:otherwise>
  </xsl:choose>
  <xsl:text>,
Run Code Online (Sandbox Code Playgroud)

(为简单起见,我跳过了一些“最后一个元素不加逗号”的代码)

本示例将不会为de生成正确的值

我一直在努力让它适用于变量de,但到目前为止我还没有成功。

使用如下结构:

<xsl:when test="string-length(preceding-sibling::enumValue[1]/@datavalue)&gt;0">
    <xsl:value-of select="preceding-sibling::enumValue/@data + 1"/>
</xsl:when>
Run Code Online (Sandbox Code Playgroud)

...仅适用于指定值(在本例中为d)之后的第一个。

谁能帮我?我可能在程序上想得太多...

Dim*_*hev 4

使用键的非递归解决方案

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:strip-space elements="*"/>
 <xsl:output method="text"/>

 <xsl:key name="koffsetEnums" match="enumValue[@data]"
  use="generate-id()"/>

    <xsl:template match="enum">
      enum <xsl:value-of select="@name"/> {
      <xsl:apply-templates select="enumValue"/>
      }
    </xsl:template>

    <xsl:template match="enumValue">
      <xsl:value-of select="concat(@name, ' = ')"/>

      <xsl:variable name="voffsetValueId" select=
       "generate-id((. | preceding-sibling::enumValue)
                                            [@data][last()]
                  )"/>

      <xsl:choose>
        <xsl:when test="not($voffsetValueId)">
          <xsl:value-of select="concat(position(),'&#xA;      ')"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:variable name="vinitOffset" select=
           "key('koffsetEnums', $voffsetValueId)/@data"
           />

           <xsl:value-of select=
            "$vinitOffset
            +
               count(preceding-sibling::enumValue)
             -
               count(key('koffsetEnums', $voffsetValueId)/preceding-sibling::enumValue)
            "
            />
           <xsl:text>&#xA;      </xsl:text>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:template>

</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

当上述转换应用于最初提供的 XML 文档时

<enum name="anenum">
    <enumValue name="a"/>
    <enumValue name="b"/>
    <enumValue name="c" data="10"/>
    <enumValue name="d" />
    <enumValue name="e" />
</enum>
Run Code Online (Sandbox Code Playgroud)

产生所需的结果

enum anenum {
      a = 1
      b = 2
      c = 10
      d = 11
      e = 12

      }
Run Code Online (Sandbox Code Playgroud)