在for-each中选择任意兄弟

时间:2011-12-02 22:12:55

标签: xslt

我循环遍历一组节点,每个节点都有两个元素,并希望为每个组输出一个两列表。该表按字母顺序排序,沿第一列向下排序,然后沿第二列向下排序。我正在对第一个元素进行分组,然后在两列中输出每个第二个元素。

示例数据来源:

<ArrayOfEIS_CT_AssignmentByRegion
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <EIS_CT_AssignmentByRegion>
        <Region>MIDDLE EAST, NORTH AFRICA and EUROPE</Region>            
        <CountryName>IRAQ</CountryName>            
    </EIS_CT_AssignmentByRegion>
    <EIS_CT_AssignmentByRegion>
        <Region>MIDDLE EAST, NORTH AFRICA and EUROPE</Region>
        <CountryName>JORDAN</CountryName>
    </EIS_CT_AssignmentByRegion>
    <EIS_CT_AssignmentByRegion>
        <Region>MIDDLE EAST, NORTH AFRICA and EUROPE</Region>
        <CountryName>GAZA AND WEST BANK</CountryName>
    </EIS_CT_AssignmentByRegion>
    <EIS_CT_AssignmentByRegion>
        <Region>MIDDLE EAST, NORTH AFRICA and EUROPE</Region>
        <CountryName>KUWAIT</CountryName>
    </EIS_CT_AssignmentByRegion>    
    <EIS_CT_AssignmentByRegion>
        <Region>SUBSAHARAN AFRICA</Region>
        <CountryName>TOGO</CountryName>
    </EIS_CT_AssignmentByRegion>
    <EIS_CT_AssignmentByRegion>
        <Region>SUBSAHARAN AFRICA</Region>
        <CountryName>ZIMBABWE</CountryName>
    </EIS_CT_AssignmentByRegion>
    <EIS_CT_AssignmentByRegion>
        <Region>SUBSAHARAN AFRICA</Region>
        <CountryName>ZAMBIA</CountryName>
    </EIS_CT_AssignmentByRegion>
    <EIS_CT_AssignmentByRegion>
        <Region>SUBSAHARAN AFRICA</Region>
        <CountryName>UGANDA</CountryName>
    </EIS_CT_AssignmentByRegion>
</ArrayOfEIS_CT_AssignmentByRegion>

XSLT:

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:w="http://schemas.microsoft.com/office/word/2006/wordml">
    <xsl:output method="xml" indent="yes" encoding="utf-8"/>    
    <xsl:key name="list-by-region" match="EIS_CT_AssignmentByRegion" use="concat(generate-id(..), '|', Region)"/>
    <xsl:template match="/ArrayOfEIS_CT_AssignmentByRegion">
        <html>
            <body>
                <xsl:for-each select="EIS_CT_AssignmentByRegion[generate-id() = generate-id(key('list-by-region', concat(generate-id(..), '|', Region))[1])]">                    
                    <xsl:sort select="Region" />
                    <xsl:sort select="CountryName" />
                    <xsl:variable name="halfIndex" select="floor(count(key('list-by-region', concat(generate-id(..), '|', Region))) div 2)" />
                    <table>
                        <thead>
                            <tr>
                                <th colspan="2">
                                    <xsl:value-of select="Region" />
                                </th>
                            </tr>
                        </thead>
                        <tbody>
                            <xsl:for-each select="key('list-by-region', concat(generate-id(..), '|', Region))">
                                <xsl:sort select="CountryName" />
                                <xsl:variable name="countryColumn2" select="following-sibling::*[position() = $halfIndex]" />
                                <xsl:if test="position() &lt;= $halfIndex">
                                    <tr>
                                        <td>
                                            <xsl:value-of select="CountryName" />
                                        </td>
                                        <td>
                                            <xsl:value-of select="$countryColumn2" />
                                        </td>
                                    </tr>
                                </xsl:if>
                            </xsl:for-each>
                        </tbody>
                    </table>
                </xsl:for-each>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>

我想要的输出是:

    <html>
    <body>
    <table>
        <thead>
            <tr>
                <th colspan="2">
                    MIDDLE EAST, NORTH AFRICA and EUROPE
                </th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>
                    GAZA AND WEST BANK
                </td>
                <td>
                    JORDAN
                </td>
            </tr>
            <tr>
                <td>
                    IRAQ
                </td>
                <td>
                    KUWAIT
                </td>
            </tr>
        </tbody>
    </table>
    <table>
        <thead>
            <tr>
                <th colspan="2">
                    SUBSAHARAN AFRICA
                </th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>
                    TOGO
                </td>
                <td>
                    ZAMBIA
                </td>
            </tr>
            <tr>
                <td>
                    UGANDA
                </td>
                <td>
                    ZIMBABWE
                </td>
            </tr>
        </tbody>
    </table>
    </body>
</html>

我的方法是只处理每组的一半,并从后半部分选择国家,然后在第二列输出。我的问题是,对于某些组,正在选择错误的国家/地区。通常,选择来自另一组的国家。

为了进行测试,我按顺序输出了所有国家/地区,单列,并且正在对它们进行分组和正确排序。所以这一行

<xsl:variable name="countryColumn2" 
     select="following-sibling::*[position() = $halfIndex]" />

对于某些组,保留当前上下文以选择兄弟节点。有任何想法吗?感谢。

1 个答案:

答案 0 :(得分:1)

<xsl:variable name="countryColumn2"       
  select="following-sibling::*[position() = $halfIndex]" /> 
     

对于某些组,请保留当前上下文以选择兄弟   节点。有什么想法吗?

好问题,+ 1。

使用<xsl:sort>排序不会更改XML文档中节点之间的原始兄弟关系

因此,对于两个节点:node1及其后续的兄弟node2,虽然node1作为排序结果出现在node2之后,但仍然是{{1} }}是node2的后续兄弟。

解决方案

  1. Pass1 :在临时树中输出排序结果,在此树中,节点之间的兄弟关系正好反映了它们的排序顺序。

  2. Pass2 :在第一遍传递结果的第二遍中继续处理。现在您可以按预期的方式使用兄弟轴。