使用XSLT分组HTML输出(muenchian分组?)

时间:2017-06-12 12:21:18

标签: xml xslt muenchian-grouping

我希望输出以特殊方式分组,也许使用muenchian分组?但我被困了

这是XML文件:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="test.xsl"?>
<NTC_PUBLICATION xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test.xsd">
    <SECTION_CONTENT_LIST_ITEM>
        <NM_TORP_NTC>
            <PUBLISH_NUMBER>138</PUBLISH_NUMBER>
            <TERM>Temporary</TERM>
            <NM_CHART_AFFECTED_LIST>
                <CHART_NUM>NZ 21 (INT 641), NZ 522, NZ 5219</CHART_NUM>
            </NM_CHART_AFFECTED_LIST>
        </NM_TORP_NTC>
    </SECTION_CONTENT_LIST_ITEM>
    <SECTION_CONTENT_LIST_ITEM>
        <NM_TORP_NTC>
            <PUBLISH_NUMBER>139</PUBLISH_NUMBER>
            <TERM>Temporary</TERM>
            <NM_CHART_AFFECTED_LIST>
                <CHART_NUM>NZ 522, NZ 5321</CHART_NUM>
            </NM_CHART_AFFECTED_LIST>
        </NM_TORP_NTC>
    </SECTION_CONTENT_LIST_ITEM>
    <SECTION_CONTENT_LIST_ITEM>
        <NM_TORP_NTC>
            <PUBLISH_NUMBER>141</PUBLISH_NUMBER>
            <TERM>Preliminary</TERM>
            <NM_CHART_AFFECTED_LIST>
                <CHART_NUM>NZ 268</CHART_NUM>
            </NM_CHART_AFFECTED_LIST>
        </NM_TORP_NTC>
    </SECTION_CONTENT_LIST_ITEM>
    <SECTION_CONTENT_LIST_ITEM>
        <NM_TORP_NTC>
            <PUBLISH_NUMBER>143</PUBLISH_NUMBER>
            <TERM>Preliminary</TERM>
            <NM_CHART_AFFECTED_LIST>
                <CHART_NUM>NZ 26, NZ 268</CHART_NUM>
            </NM_CHART_AFFECTED_LIST>
        </NM_TORP_NTC>
    </SECTION_CONTENT_LIST_ITEM>
</NTC_PUBLICATION>

这是我到目前为止的XSLT样式表:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:set="http://exslt.org/sets" xmlns:exslt="http://exslt.org/common" exclude-result-prefixes="msxsl exslt">
    <xsl:output method="html" encoding="UTF-8" indent="yes"
        doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
        doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"/>
    <xsl:key name="item" match="item" use="@chart"/>
    <xsl:template match="/">
        <div>
            <xsl:variable name="result">
                <xsl:for-each select="//NM_TORP_NTC">
                    <xsl:call-template name="split">
                        <xsl:with-param name="notice" select="PUBLISH_NUMBER"/>
                        <xsl:with-param name="string" select="NM_CHART_AFFECTED_LIST/CHART_NUM"/>
                        <xsl:with-param name="term" select="TERM"/>
                    </xsl:call-template>
                </xsl:for-each>
            </xsl:variable>
            <xsl:copy-of select="$result"/>
            <table style="padding-left:200px;align:center;">
                <xsl:choose>
                    <xsl:when test="function-available('msxsl:node-set')">
                        <xsl:call-template name="sub-class">
                            <xsl:with-param name="result" select="msxsl:node-set($result)"/>
                        </xsl:call-template>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:call-template name="sub-class">
                            <xsl:with-param name="result" select="exslt:node-set($result)"/>
                        </xsl:call-template>
                    </xsl:otherwise>
                </xsl:choose>
            </table>
            <!-- Apply the templates for each Notice -->
            <xsl:apply-templates select="SECTION_CONTENT_LIST_ITEM/NM_TORP_NTC"/>
        </div>
    </xsl:template>

    <xsl:template name="split">
        <xsl:param name="notice"/>
        <xsl:param name="string"/>
        <xsl:param name="term"/>
        <xsl:if test="substring-after($string,',')!=''">
            <item>
                <xsl:attribute name="notice">
                    <xsl:value-of select="$notice"/>
                </xsl:attribute>
                <xsl:attribute name="chart">
                    <xsl:value-of select="substring-before($string,',')"/>
                </xsl:attribute>
                <xsl:attribute name="term">
                    <xsl:value-of select="$term"/>
                </xsl:attribute>
            </item>
        </xsl:if>
        <xsl:choose>
            <xsl:when test="substring-after($string,',')!=''">
                <xsl:call-template name="split">
                    <xsl:with-param name="notice" select="$notice"/>
                    <xsl:with-param name="string" select="substring-after($string,',')"/>
                    <xsl:with-param name="term" select="$term"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:when test="not(contains($string,','))">
                <item>
                    <xsl:attribute name="notice">
                        <xsl:value-of select="$notice"/>
                    </xsl:attribute>
                    <xsl:attribute name="chart">
                        <xsl:value-of select="$string"/>
                    </xsl:attribute>
                    <xsl:attribute name="term">
                        <xsl:value-of select="$term"/>
                    </xsl:attribute>
                </item>
            </xsl:when>
        </xsl:choose>
    </xsl:template>

    <xsl:template name="sub-class">
        <xsl:param name="result"/>
        <xsl:for-each select="$result/item[count(. | key('item', @chart)[1]) = 1]">
            <xsl:sort select="@chart" data-type="text" order="ascending"/>
            <tr>
                <td>
                    <xsl:value-of select="@chart"/>
                </td>
                <td>
                    <xsl:for-each select="key('item', @chart)">
                        <xsl:sort select="@notice" data-type="number"/>
                        <xsl:variable name="pos" select="position()"/>
                        <xsl:if test="$pos!=1">
                            <xsl:text>, </xsl:text>
                        </xsl:if>
                        <xsl:value-of select="@notice"/><xsl:text> </xsl:text>
                        <xsl:if test="@term='Temporary'">
                            <xsl:text>(T)</xsl:text>
                        </xsl:if>
                        <xsl:if test="@term='Preliminary'">
                            <xsl:text>(P)</xsl:text>
                        </xsl:if>
                    </xsl:for-each>
                </td>
            </tr>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

目前输出是这样的((T)用于临时,(P)用于初步):

NZ 268     143 (P)
NZ 5219    138 (T)
NZ 522     138 (T)
NZ 5321    139 (T)
NZ 21      138 (T)
NZ 26      143 (P)
NZ 268     141 (P)
NZ 522     139 (T)

我希望将输出分组,如表所示:

NZ 21      138 (T)
NZ 26      143 (P)
NZ 268     141 (P), 143 (P)
NZ 522     139 (T), 141 (P)
NZ 5219    138 (T)
NZ 5321    139 (T)

1 个答案:

答案 0 :(得分:2)

我看到你的XSLT复制了$result变量(用于调试),如果仔细观察,你想要分组的项目之间存在差异

<item notice="141" chart="NZ 268" term="Preliminary"></item>
....
<item notice="143" chart=" NZ 268" term="Preliminary"></item>

chart属性的某个值之前有一个空格,这意味着就分组而言,值是不同的。

解决方案只是在创建normalize-space属性时使用chart修剪空格。

尝试将split模板更改为此....

<xsl:template name="split">
    <xsl:param name="notice"/>
    <xsl:param name="string"/>
    <xsl:param name="term"/>
    <xsl:if test="substring-after($string,',')!=''">
        <item>
            <xsl:attribute name="notice">
                <xsl:value-of select="$notice"/>
            </xsl:attribute>
            <xsl:attribute name="chart">
                <xsl:value-of select="normalize-space(substring-before($string,','))"/>
            </xsl:attribute>
            <xsl:attribute name="term">
                <xsl:value-of select="$term"/>
            </xsl:attribute>
        </item>
    </xsl:if>
    <xsl:choose>
        <xsl:when test="substring-after($string,',')!=''">
            <xsl:call-template name="split">
                <xsl:with-param name="notice" select="$notice"/>
                <xsl:with-param name="string" select="substring-after($string,',')"/>
                <xsl:with-param name="term" select="$term"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:when test="not(contains($string,','))">
            <item>
                <xsl:attribute name="notice">
                    <xsl:value-of select="$notice"/>
                </xsl:attribute>
                <xsl:attribute name="chart">
                    <xsl:value-of select="normalize-space($string)"/>
                </xsl:attribute>
                <xsl:attribute name="term">
                    <xsl:value-of select="$term"/>
                </xsl:attribute>
            </item>
        </xsl:when>
    </xsl:choose>
</xsl:template>

或许可以简化一下......

<xsl:template name="split">
    <xsl:param name="notice"/>
    <xsl:param name="string"/>
    <xsl:param name="term"/>
    <xsl:if test="normalize-space($string)!=''">
        <item>
            <xsl:attribute name="notice">
                <xsl:value-of select="$notice"/>
            </xsl:attribute>
            <xsl:attribute name="chart">
                <xsl:value-of select="normalize-space(substring-before(concat($string, ','),','))"/>
            </xsl:attribute>
            <xsl:attribute name="term">
                <xsl:value-of select="$term"/>
            </xsl:attribute>
        </item>
    </xsl:if>
    <xsl:if test="contains($string,',')">
        <xsl:call-template name="split">
            <xsl:with-param name="notice" select="$notice"/>
            <xsl:with-param name="string" select="substring-after($string,',')"/>
            <xsl:with-param name="term" select="$term"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>