使用 XSLT 对 HTML 输出进行分组(muenchian 分组?)
Posted
技术标签:
【中文标题】使用 XSLT 对 HTML 输出进行分组(muenchian 分组?)【英文标题】:Group a HTML output with XSLT(muenchian grouping?) 【发布时间】:2017-11-13 22:11:23 【问题描述】:我想以一种特殊的方式对输出进行分组,也许使用 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)
【问题讨论】:
请将示例简化为仅演示问题所必需的内容 - 请参阅:minimal reproducible example。 这已经从一个更大的文件中减少了。我认为这里的一切都是必要的。 我不认为标记化部分对于对其结果进行分组是必要的。 【参考方案1】:我看到您的 XSLT 复制了 $result
变量(用于调试),如果您仔细观察,您希望分组的项目之间存在差异
<item notice="141" chart="NZ 268" term="Preliminary"></item>
....
<item notice="143" chart=" NZ 268" term="Preliminary"></item>
chart
属性的值之一之前有一个空格,这意味着就分组而言,这些值是不同的。
解决方案就是在创建chart
属性时使用normalize-space
修剪空格。
尝试将您的 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>
【讨论】:
工作得很好!非常感谢:)以上是关于使用 XSLT 对 HTML 输出进行分组(muenchian 分组?)的主要内容,如果未能解决你的问题,请参考以下文章
使用 XSLT 程序对具有逗号分隔值的 XML 元素进行分组