我正在研究java代码生成和XSLT,其中有许多<xsl:if>
或<xsl:choose>
不可维护。
字段顺序对于消息很重要,我发现生成不同字段的唯一方法是在不同属性上使用switch case。
这是一个示例XML数据:
<?xml version="1.0" encoding="ISO-8859-1"?>
<message class="Message" length="28" id="0x12457836"
package="org.goinfre.mail.data">
<comment>bulk message</comment>
<field name="state" type="short" size="2"/>
<field name="reserve" size="2" reserved="true"/>
<field name="reserve" size="1" reserved="true"/>
<field name="identification" type="char">
<array size="32" sizeName="IDENT_SIZE" encoding="UTF8" />
</field>
<field name="validity" type="int" size="4"/>
<field name="voie" type="long" size="8"/>
</message>
相应的XSL太长,但是例如在每个字段上我使用<xsl:choose>
,因为编码和解码消息缓冲区的顺序很重要。我需要多次使用每个字段。
<xsl:template match="/message">
[...]
<xsl:apply-templates select="field" mode="generateField"/><xsl:text>
[...]
@Override
public byte[] toByteArray() {
ByteBuffer buffer = ByteBuffer.allocate(LENGTH);
super.toByteArray(buffer);
</xsl:text>
<xsl:apply-templates select="field" mode="generateBuffer"/>
<xsl:text>
return buffer.array();
}
</xsl:template>
<!--
*****************************************************************
** Generate a private field declaration.
**************************************************************-->
<xsl:template match="field" mode="generateField">
<xsl:choose>
<xsl:when test="array">
private int <xsl:value-of select="array/@sizeName"/><xsl:text> = </xsl:text><xsl:value-of select="array/@size"/>;
private <xsl:value-of select="@type"/><xsl:text>[] </xsl:text><xsl:value-of select="@name"/>
<xsl:text> = new </xsl:text><xsl:value-of select="@type"/>
<xsl:text>[</xsl:text><xsl:value-of select="array/@sizeName"/><xsl:text>];</xsl:text>
</xsl:when>
<xsl:when test="not(@reserved)">
private <xsl:value-of select="@type"/><xsl:text> </xsl:text><xsl:value-of select="@name"/>;
</xsl:when>
</xsl:choose>
</xsl:template>
我想为每个字段使用不同的元素(字段数组,字段保留字段,字段...),但不遵守顺序。
注意:我现在仍然可以更改XML的格式。
答案 0 :(得分:2)
创建更专业的模板。将条件从模板内部的条件语句中移动到模板的匹配条件中。
注意:多个模板可能与元素匹配。如果它们在匹配标准中具有相同的特异性级别,那么它们将获得相同的计算优先级。您可能必须在模板上指定@priority
才能“打破平局”并控制应该触发哪一个。在这个例子中,我将priority="1"
添加到field[array]
的模板中,以确保它匹配而不是字段[not(@reserved)]`的匹配。
例如:
<!--
*****************************************************************
** Generate a private field declaration
for fields that have array elements.
**************************************************************-->
<xsl:template match="field[array]" priority="1" mode="generateField">
private int <xsl:value-of select="array/@sizeName"/><xsl:text> = </xsl:text><xsl:value-of select="array/@size"/>;
private <xsl:value-of select="@type"/><xsl:text>[] </xsl:text><xsl:value-of select="@name"/>
<xsl:text> = new </xsl:text><xsl:value-of select="@type"/>
<xsl:text>[</xsl:text><xsl:value-of select="array/@sizeName"/><xsl:text>];</xsl:text>
</xsl:template>
<!--
*****************************************************************
** Generate a private field declaration
for fields that do not have the attribute reserved.
**************************************************************-->
<xsl:template match="field[not(@reserved)]" mode="generateField">
private <xsl:value-of select="@type"/><xsl:text> </xsl:text><xsl:value-of select="@name"/>;
</xsl:template>
它还可以提高性能,因为匹配条件有机会由XSLT处理器优化。