XSLT - 根据位置添加动态变化的属性

时间:2016-11-07 01:50:53

标签: xml xslt

我有一个像这样的xml文件,

<doc>
    <lo>
        <li>text1</li>
        <li>text2</li>
        <li>text3</li>
        <li>text4</li>
        <li>text5</li>
        <li>text6</li>
        <li>text7</li>
        <li>text8</li>
        <li>text9</li>
        <li>text10</li>
        <li>text11</li>
        <li>text12</li>
        <li>text13</li>
        <li>text14</li>
        <li>text15</li>
        <li>text16</li>
    </lo>
</doc>

我需要动态地将padding属性添加到列表项中。添加padding的序列从25开始,每个乘法器5应该通过不利序列添加填充值。

例如:

5th list item: padding=25
10th list item: padding=20
15th list item: padding=15
10th list item: padding=10

并且对于每个第一个前面的兄弟和第5个乘法器的后续兄弟,得到来自中间第5个乘数的填充值-3。

例如:

4th list item: padding=22
5th list item: padding=25
6th list item: padding=22
9th list item: padding=17
10th list item: padding=20
11th list item: padding=17

因此样本预期输出应该如下所示,

<doc>
    <lo>
        <li>text1</li>
        <li>text2</li>
        <li>text3</li>
        <li padding ="22">text4</li>
        <li padding ="25">text5</li>
        <li padding ="22">text6</li>
        <li>text7</li>
        <li>text8</li>
        <li padding ="17">text9</li>
        <li padding ="20">text10</li>
        <li padding ="17">text11</li>
        <li>text12</li>
        <li>text13</li>
        <li padding ="12">text14</li>
        <li padding ="15">text15</li>
        <li padding ="12">text16</li>
    </lo>
</doc>

我写了以下xslt来执行此任务,

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

    <xsl:template match="li">
        <li>
            <xsl:choose>
                <xsl:when test="(abc:get-list-position(.) mod 5) =0">
                    <xsl:attribute name="padding" select="25"/>
                </xsl:when>
            </xsl:choose>
            <xsl:apply-templates/>
        </li>
    </xsl:template>

    <xsl:function name="abc:get-list-position">
        <xsl:param name="node"/>

        <xsl:sequence select="count($node/preceding-sibling::li) + 1"/>
    </xsl:function>

但是由于XSLT没有增量变量和前进循环,我努力进一步扩展我的逻辑。任何人都可以建议我如何使用XSLT来完成这项任务。

1 个答案:

答案 0 :(得分:2)

XSLT已经有position()功能,您无需重新发明它。

AFAICT,你想做:

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="li[position() gt 3 and position() mod 5 = (0, 1, 4)]">
    <xsl:variable name="x" select="6 - (position() + 1) idiv 5" />
    <xsl:copy>
        <xsl:attribute name="padding" select="5 * $x - 3 * number(position() mod 5 != 0)"/>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>