How to create XSLT transformation for srcML?

2019-08-18 18:59发布

I have a question about XSL transformation. Lets take an example (in srcML) which represents a typedef enum in C:

<typedef>typedef <type><enum>enum <name>SomeEnum</name>
<block>{
 <expr><name>Value0</name> = 0</expr>,
 <expr><name>Value1</name> = <name>SOMECONST</name></expr>,
 <expr><name>Value2</name> = <name>SOMECONST</name> + 1</expr>,
 <expr><name>ValueTop</name></expr>
}</block></enum></type> <name>TSomeEnum</name>;</typedef>

C version:

typedef enum SomeEnum
{
    Value0 = 0,
    Value1 = SOMECONST,
    Value2 = SOMECONST + 1,
    ValueTop
} TSomeEnum;

How to define an <xsl:template> to remove the line with, for example, Value2?

How to define an <xsl:template> to remove the last line (with ValueTop), including the preceding comma?

标签: xslt
1条回答
Viruses.
2楼-- · 2019-08-18 19:45

This is a bit tricky due to the "interspersed text" nature of your input XML. Especially comma handling is not trivial, and my proposed solution is probably wrong (even though it works for this particular input). I recommend giving the comma handling part a lot more thought since C syntax is complex and I don't know much about srcML.

Anyway, here is my attempt.

<xsl:stylesheet 
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:src="http://www.sdml.info/srcML/src"
  xmlns="http://www.sdml.info/srcML/src"
>
  <!-- the identity template copies everything as is -->
  <xsl:template match="node() | @*">
    <xsl:copy>
      <xsl:apply-templates select="node() | @*" />
    </xsl:copy>
  </xsl:template>

  <!-- empty templates will remove any matching elements from the output -->
  <xsl:template match="src:expr[src:name = 'Value2']" />
  <xsl:template match="src:expr[last()]" />

  <!-- this template handles the commata after expressions -->
  <xsl:template match="text()[normalize-space() = ',']">
    <!-- select the following node, but only if it is an <expr> element -->
    <xsl:variable name="expr" select="following-sibling::*[1][self::src:expr]" />

    <!-- apply templates to it, save the result -->
    <xsl:variable name="check">
      <xsl:apply-templates select="$expr" />
    </xsl:variable>

    <!-- if something was returned, then this comma needs to be copied -->
    <xsl:if test="$check != ''">
      <xsl:copy />
    </xsl:if>
  </xsl:template>

</xsl:stylesheet>

My input was (I used the srcML namespace for the sake of the example):

<unit xmlns="http://www.sdml.info/srcML/src">
<typedef>typedef <type><enum>enum <name>SomeEnum</name>
<block>{
 <expr><name>Value0</name> = 0</expr>,
 <expr><name>Value1</name> = <name>SOMECONST</name></expr>,
 <expr><name>Value2</name> = <name>SOMECONST</name> + 1</expr>,
 <expr><name>ValueTop</name></expr>
}</block></enum></type> <name>TSomeEnum</name>;</typedef>
</unit

and the result:

<unit xmlns="http://www.sdml.info/srcML/src">
<typedef>typedef <type><enum>enum <name>SomeEnum</name>
<block>{
 <expr><name>Value0</name> = 0</expr>,
 <expr><name>Value1</name> = <name>SOMECONST</name></expr>
}</block></enum></type> <name>TSomeEnum</name>;</typedef>
</unit>
查看更多
登录 后发表回答