如何使用XSLT使用`<xsl:apply-template>`来遵守XML顺序?</xsl:apply-template>

时间:2011-10-14 09:59:53

标签: xml xslt xpath code-generation

我正在研究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>

我想为每个字段使用不同的元素(字段数组,字段保留字段,字段...),但不遵守顺序。

  • 这是使用XSL的有效方法吗?
  • 您对如何使用XSLT生成代码有任何提示吗?

注意:我现在仍然可以更改XML的格式。

1 个答案:

答案 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处理器优化。