XSL迭代属性并忽略一些元素

时间:2012-07-10 13:39:17

标签: xslt-1.0

我需要做一些相当简单的事情来迭代我的XML中的元素(XML下的更多解释)

<form>
<field index="1" name="field_X_1" group="firstGroup" type="String">
<value>Value of Field X 1 of first group</value>
</field>

<field index="1" name="field_Y_1" group="firstGroup" type="String">
<value>Value of Field Y 1 of first group</value>
</field>

<field index="2" name="field_X_2" group="firstGroup" type="String">
<value>Value of Field X 2 of first group</value>
</field>

<field index="2" name="field_Y_2" group="firstGroup" type="String">
<value>Value of Field Y 2 of first group</value>
</field>

<field index="1" name="field_A_1" group="secondGroup" type="String">
<value>Value of Field A 1 of second group</value>
</field>

<field index="1" name="field_B_1" group="secondGroup" type="String">
<value>Value of Field B 1 of second group</value>
</field>

<field index="2" name="field_A_2" group="secondGroup" type="String">
<value>Value of Field A 2 of second group</value>
</field>

<field index="2" name="field_B_2" group="secondGroup" type="String">
<value>Value of Field B 2 of second group</value>
</field>


</form>

现在我正在迭代firstGroup的所有字段,每当我发现索引已经改变时(通过比较索引与sibbling的索引)我添加新行字符)。 问题是我只需要迭代索引(但仍然在firstGroup和secondGroup之间保持干扰)。

我的输出应该是

Value of Field X 1 of first group, Value of Field Y 1 of first group
Value of Field X 2 of first group, Value of Field Y 2 of first group
Value of Field A 1 of second group, Value of Field B 1 of second group
Value of Field A 2 of second group, Value of Field B 2 of second group
etc

我的XSL现在看起来像

    <xsl:for-each select='/form/field[@group="firstGroup"]'>
                <xsl:sort select="@index" order="ascending"></xsl:sort>     
                <xsl:if test='preceding-sibling::*[@group="firstGroup"][1]/@index != @index and count(preceding-sibling::*) != 0 '>
                    <xsl:text>&#xa;</xsl:text>
                </xsl:if>
                <xsl:value-of select="//field[@name=concat('field_X_', @index,')]/value"/>                              

                <xsl:value-of select="//field[@name=concat('field_Y_', @index,')]/value"/>                              
     </xsl:for-each>    
<!-- Differente iteration for second group-->
<xsl:text>&#xa;</xsl:text>
<xsl:for-each select='/form/field[@group="firstGroup"]'>
                <xsl:sort select="@index" order="ascending"></xsl:sort>     
                <xsl:if test='preceding-sibling::*[@group="firstGroup"][1]/@index != @index and count(preceding-sibling::*) != 0 '>
                    <xsl:text>&#xa;</xsl:text>
                </xsl:if>
                <xsl:value-of select="//field[@name=concat('field_A_', @index,')]/value"/>                              

                <xsl:value-of select="//field[@name=concat('field_B_', @index,')]/value"/>                              
     </xsl:for-each>    

1 个答案:

答案 0 :(得分:2)

<xsl:output method="text" />

<xsl:template match="form">
    <!--* find all the groups *-->
    <xsl:variable name="groups">
        <xsl:call-template name="get-group-names">
            <xsl:with-param name="nodes" select="field" />
        </xsl:call-template>
    </xsl:variable>

    <xsl:call-template name="process-all-groups">
        <xsl:with-param name="group-names" select="$groups" />
    </xsl:call-template>

</xsl:template>

<xsl:template name="get-group-names">
    <xsl:param name="nodes" />
    <xsl:param name="result-so-far" />

    <xsl:choose>
        <xsl:when test="not($nodes)">
            <xsl:value-of select="$result-so-far" />
        </xsl:when>
        <xsl:when test="contains(
            concat(' ', $result-so-far),
            concat(' ', $nodes[1]/@group, ' '))" >

            <xsl:call-template name="get-group-names">
                <xsl:with-param name="nodes" select="$nodes[position() &gt; 1]" />
                <xsl:with-param name="result-so-far" select="$result-so-far" />
            </xsl:call-template>
        </xsl:when>

        <xsl:otherwise>
            <xsl:call-template name="get-group-names">
                <xsl:with-param name="nodes" select="$nodes[position() &gt; 1]" />
                <xsl:with-param name="result-so-far"
                    select="concat($result-so-far, $nodes[1]/@group, ' ')" />
            </xsl:call-template>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

<xsl:template name="process-all-groups">
    <xsl:param name="group-names" />

    <xsl:variable name="group" select="substring-before($group-names, ' ')"/>

    <xsl:if test="not(string-length($group) = 0)">
        <xsl:call-template name="index">
            <xsl:with-param name="n" select="1" />
            <xsl:with-param name="group" select="$group" />
        </xsl:call-template>

        <xsl:call-template name="process-all-groups">
            <xsl:with-param name="group-names"
                select="substring-after($group-names, ' ')" />
        </xsl:call-template>

    </xsl:if>
</xsl:template>

<xsl:template name="index">
    <xsl:param name="n" select="1" />
    <xsl:param name="group" />

    <xsl:variable name="with-n"
        select="/form/field[@group = $group][@index = $n]" />

    <xsl:if test="$with-n">

        <xsl:for-each select="$with-n">
            <xsl:sort use="@index" order="ascending" />

            <xsl:value-of select="value" />
            <xsl:if test="not(position() = last())">
                <xsl:text>,</xsl:text>
            </xsl:if>
        </xsl:for-each>
        <xsl:text>&#xa;</xsl:text>

        <xsl:call-template name="index">
            <xsl:with-param name="n" select="$n + 1" />
            <xsl:with-param name="group" select="$group" />
        </xsl:call-template>
    </xsl:if>
</xsl:template>
<xsl:template match="field"></xsl:template>