我正在尝试构建一个解析整个xml文档的列表。我需要列出数字名称,然后列出alpha名称。列表看起来应该是这样的。
6
6600 Training
6500 Training
A
Accelerated Training
T
Training
这是xml的片段。
<courses>
<course>
<name>Accelerated Training</name>
</course>
<course>
<name>6600 Training</name>
</course>
<course>
<name>Training</name>
</course>
<course>
<name>6500 Training</name>
</course>
</courses>
这是我目前正在使用的代码。我在网站上的另一个问题中发现了这一点,并对其进行了一些定制。目前它没有考虑到我需要按编号解析,它也会按字母顺序返回。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="vLower" select= "'abcdefghijklmnopqrstuvwxyz'"/>
<xsl:variable name="vUpper" select= "'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
<xsl:key name="kTitleBy1stLetter" match="courses/course" use="substring(name,1,1)"/>
<xsl:template match="/*">
<xsl:for-each select="course [generate-id() = generate-id(key('kTitleBy1stLetter', substring(name,1,1)) [1] ) ]">
<xsl:variable name="v1st" select="substring(name,1,1)"/>
<h2><xsl:value-of select="$v1st"/></h2>
<div class="{translate($v1st, $vUpper, $vLower)}-content">
<ul>
<xsl:for-each select="key('kTitleBy1stLetter',$v1st)">
<li><xsl:value-of select="name"/></li>
</xsl:for-each>
</ul>
</div>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
答案 0 :(得分:7)
基本上,您需要按第一个字母分组,然后按<name>
排序。你的Muenchian分组方法已经很好了。
我建议另一种方法更容易:
<xsl:key name="kInitial" match="course" use="substring(name, 1, 1)" />
<xsl:template match="courses">
<xsl:apply-templates select="course" mode="initial">
<xsl:sort select="name" />
</xsl:apply-templates>
</xsl:template>
<xsl:template match="course" mode="initial">
<xsl:variable name="initial" select="substring(name, 1, 1)" />
<xsl:variable name="courses" select="key('kInitial', $initial)" />
<xsl:if test="generate-id() = generate-id($courses[1])">
<h2><xsl:value-of select="$initial"/></h2>
<ul>
<xsl:apply-templates select="$courses">
<xsl:sort select="name" />
</xsl:apply-templates>
</ul>
</xsl:if>
</xsl:template>
<xsl:template match="course">
<li>
<xsl:value-of select="name"/>
</li>
</xsl:template>
输出:
<h2>6</h2>
<ul>
<li>6500 Training</li>
<li>6600 Training</li>
</ul>
<h2>A</h2>
<ul>
<li>Accelerated Training</li>
</ul>
<h2>T</h2>
<ul>
<li>Training</li>
</ul>
编辑:为了易读,我遗漏了第一个字母的上半身。正确的密钥就是这个(你不能在密钥中使用变量,因此是文字字母串):
<xsl:key name="kInitial" match="course" use="
translate(
substring(name, 1, 1),
'abcdefghijklmnopqrstuvwxyz',
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
)
" />
第二个模板中的$initial
变量当然也是如此,但实际上你可以在这里再次使用变量。
编辑#2:由于排序也区分大小写,因此您可以使用相同的表达式:
<xsl:sort select="translate(substring(name, 1, 1), $vLower, $vUpper)" />
答案 1 :(得分:2)
XSLT 2.0解决方案:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/*">
<xsl:for-each-group select="course"
group-by="upper-case(substring(name,1,1))">
<xsl:sort select="current-grouping-key()"/>
<xsl:sequence select=
"concat('
', current-grouping-key())"/>
<xsl:for-each select="current-group()">
<xsl:sort select="upper-case(name)"/>
<xsl:sequence select="concat('
	', name)"/>
</xsl:for-each>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
将上述转换应用于最初提供的XML文档:
<courses>
<course>
<name>Accelerated Training</name>
</course>
<course>
<name>6600 Training</name>
</course>
<course>
<name>Training</name>
</course>
<course>
<name>6500 Training</name>
</course>
</courses>
生成想要的结果(为简单起见,文本格式 - 生成Html留给读者练习:)
6
6500 Training
6600 Training
A
Accelerated Training
T
Training
请注意:
使用 <xsl:for-each-group>
XSLT 2.0指令
使用 current-grouping-key()
和 current-group()
XSLT 2.0函数。
使用 upper-case()
XPath 2.0功能
答案 2 :(得分:0)
如果你想要任何复杂的数字部分是很棘手的,但根据你理想的输出,你所缺少的只是一个简单的sort你的每个人:
<xsl:sort select="key('kTitleBy1stLetter', substring(name,1,1))" />
警告:我没有声称这是最好或唯一或其他方法,只是这完全停止,并使用你已有的。