Html 如何使用XSLT构建字母顺序的手风琴?
给定以下XML:Html 如何使用XSLT构建字母顺序的手风琴?,html,xslt,Html,Xslt,给定以下XML: <databases> <database> <title_display>Aardvark</title_display> </database> <database> <title_display>Apple</title_display> </database> <database>
<databases>
<database>
<title_display>Aardvark</title_display>
</database>
<database>
<title_display>Apple</title_display>
</database>
<database>
<title_display>Blue</title_display>
</database>
<database>
<title_display>Car</title_display>
</database>
</databases>
土豚
苹果
蓝色
汽车
如何使用XSLT获得以下HTML输出
<h2>A</h2>
<div class="a-content">
<ul>
<li>Aardvark</li>
<li>Aardvark</li>
</ul>
</div>
<h2>B</h2>
<div class="b-content">
<ul>
<li>Blue</li>
</ul>
</div>
<h2>C</h2>
<div class="c-content">
<ul>
<li>Car</li>
</ul>
</div>
A
- 土豚
- 土豚
B
- 蓝色的
C
- 汽车
我可以放心地假设所有
元素都已按字母顺序排列。谢谢
编辑:为了便于将来参考,“Accordion”部分是用JavaScript将HTML转换成Accordion元素。您可以尝试将其用于分组。请注意,xslt2.0为每个组都提供了一个示例,这使得这一过程更加容易
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="html"/>
<xsl:template match="/databases">
<xsl:for-each select="database">
<xsl:variable name="Init" select="substring(title_display,1,1)"/>
<xsl:if test="not(preceding-sibling::*[substring(title_display,1,1)=$Init])">
<h2><xsl:value-of select="$Init"/></h2>
<div>
<xsl:attribute name="class">
<xsl:value-of select="$Init"/><xsl:text>-content</xsl:text>
</xsl:attribute>
<ul>
<xsl:for-each select="../database[substring(title_display,1,1)=$Init]">
<li><xsl:value-of select="title_display"/></li>
</xsl:for-each>
</ul>
</div>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
-内容
这是通过在所有数据库中循环来实现的,但只会为以每个字母开头的第一个数据库发送数据。然后选择以该字母开头的所有项目,并将其作为一个组进行处理
您的另一个选择是使用xslt中的分组功能。这里是Josh解决方案的一个不区分大小写的版本:
<xsl:variable name="lower">abcdefghijklmnopqrstuvwxyz</xsl:variable>
<xsl:variable name="upper">ABCDEFGHIJKLMNOPQRSTUVWXYZ</xsl:variable>
<xsl:for-each select="databases/database">
<xsl:variable name="Init" select="translate(substring(title_display,1,1), $lower, $upper)"/>
<xsl:if test="not(preceding-sibling::*[translate(substring(title_display,1,1), $lower, $upper)=$Init])">
<h2><xsl:value-of select="$Init"/></h2>
<div>
<xsl:attribute name="class">
<xsl:value-of select="translate(substring($Init,1,1), $upper, $lower)"/><xsl:text>-content</xsl:text>
</xsl:attribute>
<ul>
<xsl:for-each select="../database[translate(substring(title_display,1,1), $lower, $upper)=$Init]">
<li><xsl:value-of select="title_display"/></li>
</xsl:for-each>
</ul>
</div>
</xsl:if>
</xsl:for-each>
abcdefghijklmnopqrstuvxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
-内容
这里有一个更有效的解决方案,使用经典的Muenchian方法进行分组——使用键
此转换:
<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="database"
use="substring(title_display,1,1)"/>
<xsl:template match="/*">
<xsl:for-each select=
"database
[generate-id()
=
generate-id(key('kTitleBy1stLetter',
substring(title_display,1,1)
)[1]
)
]"
>
<xsl:variable name="v1st"
select="substring(title_display,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="title_display"/></li>
</xsl:for-each>
</ul>
</div>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
<databases>
<database>
<title_display>Aardvark</title_display>
</database>
<database>
<title_display>Apple</title_display>
</database>
<database>
<title_display>Blue</title_display>
</database>
<database>
<title_display>Car</title_display>
</database>
</databases>
<h2>A</h2>
<div class="a-content">
<ul>
<li>Aardvark</li>
<li>Apple</li>
</ul>
</div>
<h2>B</h2>
<div class="b-content">
<ul>
<li>Blue</li>
</ul>
</div>
<h2>C</h2>
<div class="c-content">
<ul>
<li>Car</li>
</ul>
</div>
应用于最初提供的XML文档时:
<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="database"
use="substring(title_display,1,1)"/>
<xsl:template match="/*">
<xsl:for-each select=
"database
[generate-id()
=
generate-id(key('kTitleBy1stLetter',
substring(title_display,1,1)
)[1]
)
]"
>
<xsl:variable name="v1st"
select="substring(title_display,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="title_display"/></li>
</xsl:for-each>
</ul>
</div>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
<databases>
<database>
<title_display>Aardvark</title_display>
</database>
<database>
<title_display>Apple</title_display>
</database>
<database>
<title_display>Blue</title_display>
</database>
<database>
<title_display>Car</title_display>
</database>
</databases>
<h2>A</h2>
<div class="a-content">
<ul>
<li>Aardvark</li>
<li>Apple</li>
</ul>
</div>
<h2>B</h2>
<div class="b-content">
<ul>
<li>Blue</li>
</ul>
</div>
<h2>C</h2>
<div class="c-content">
<ul>
<li>Car</li>
</ul>
</div>
土豚
苹果
蓝色
汽车
准确地生成所需的结果:
<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="database"
use="substring(title_display,1,1)"/>
<xsl:template match="/*">
<xsl:for-each select=
"database
[generate-id()
=
generate-id(key('kTitleBy1stLetter',
substring(title_display,1,1)
)[1]
)
]"
>
<xsl:variable name="v1st"
select="substring(title_display,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="title_display"/></li>
</xsl:for-each>
</ul>
</div>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
<databases>
<database>
<title_display>Aardvark</title_display>
</database>
<database>
<title_display>Apple</title_display>
</database>
<database>
<title_display>Blue</title_display>
</database>
<database>
<title_display>Car</title_display>
</database>
</databases>
<h2>A</h2>
<div class="a-content">
<ul>
<li>Aardvark</li>
<li>Apple</li>
</ul>
</div>
<h2>B</h2>
<div class="b-content">
<ul>
<li>Blue</li>
</ul>
</div>
<h2>C</h2>
<div class="c-content">
<ul>
<li>Car</li>
</ul>
</div>
A
- 土豚
- 苹果
B
- 蓝色的
C
- 汽车
请注意,Muenchian方法比O(N^2)解决方案的效率要高得多,O(N^2)解决方案使用所有数据库元素在前面的同级::
轴心国
此外,此解决方案将生成具有所需大小写的类
属性值谢谢!不知怎的,我在想,我必须用模板做一些奇怪的递归才能让它工作。我们常常找不到简单的解决方案,对吧?这个解决方案产生了:但需要的是:而且,如果有许多“数据库”同级,它可能会非常低效--O(N^2)。这就是我提到Muenchian方法的原因。有时,只需要更慢但更简单的方法即可。@Tyson,请查看您的问题的更有效、更准确的解决方案:)