我有以下形式的XML数据:
<table>
<col>
<name>Addresses</name>
</col>
<col>
<name>Addresses/Address1</name>
</col>
<col>
<name>Addresses/Address2</name>
</col>
<col>
<name>Addresses/Address1/Flat Number</name>
</col>
<col>
<name>Employee Name</name>
</col>
<col>
<name>Phone Number</name>
</col>
<col>
<name>Profession</name>
</col>
<col>
<name>Employee Name/First Name</name>
</col>
<col>
<name>Employee Name/Last Name</name>
</col>
<col>
<name>Employee Name/First_Name</name>
</col>
<col>
<name>Accounts/Account Name/First/Saving</name>
</col>
<col>
<name>Accounts/Account_Name/Second</name>
</col>
</table>
现在我想在这个XML上使用XSLT在HTML中创建一个类似树视图的结构。 Treeview的结构类似于以下结构:
请注意,第一次出现“/”之前的子字符串是树视图的第一级节点,第一次出现“/”后的子字符串是匹配的第一级节点的第二级节点,这只是一个2级别树视图。
此外,显示的值是唯一的。即使值在XML中重复,我们也只需要选择唯一的值。还需要考虑的另一个条件是,“”的值与没有“”的情况相同,如示例中所示:“First Name”和“First_Name”,因此我们需要在替换后显示值“ - “with”“。
<xsl:variable name="currentNode" select="//table/col" />
<xsl:key name="uniqueCategoryKey" match="record" use="name"/>
<xsl:key name="uniqueSubCategoryKey" match="record" use="substring-before(substring-after(concat(name,'/'),'/'),'/')"/>
<xsl:template match="/">
<xsl:call-template name="treeTemplate" />
</xsl:template>
<xsl:template name="treeTemplate">
<div id ="newtreeview">
<ul>
<xsl:for-each select="$currentNode[generate-id() = generate-id(key('uniqueCategoryKey', name))]">
<xsl:variable name="category" select="name"/>
<xsl:if test="string-length($category) > 0 and not(contains($category,'/'))">
<li>
<a href="#">
<xsl:value-of select="$category"/>
</a>
<xsl:if test="//record[contains(name, concat($category,'/'))]">
<ul>
<xsl:for-each select="$currentNode[generate-id() = generate-id(key('uniqueSubCategoryKey', substring-before(substring-after(concat(name,'/'),'/'),'/')))]">
<li>
<a href="#">
<xsl:variable name="subcat">
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text" select="string(substring-before(substring-after(concat(name,'/'),'/'),'/'))" />
<xsl:with-param name="replace" select="'_'" />
<xsl:with-param name="by" select="' '" />
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="$subcat"/>
</a>
</li>
</xsl:for-each>
</ul>
</xsl:if>
</li>
</xsl:if>
</xsl:for-each>
</ul>
</div>
</xsl:template>
<xsl:template name="string-replace-all">
<xsl:param name="text" />
<xsl:param name="replace" />
<xsl:param name="by" />
<xsl:choose>
<xsl:when test="contains($text, $replace)">
<xsl:value-of select="substring-before($text,$replace)" />
<xsl:value-of select="$by" />
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text"
select="substring-after($text,$replace)" />
<xsl:with-param name="replace" select="$replace" />
<xsl:with-param name="by" select="$by" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
问题是,这段代码给了我一个像
这样的输出请帮我解决这个问题。
先谢谢。
答案 0 :(得分:2)
此XSLT 1.0转换:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kCatFromName" match="name"
use="substring-before(concat(.,'/'), '/')"/>
<xsl:key name="kValFromName" match="name[contains(., '/')]"
use="concat(substring-before(.,'/'),
'+',
translate(
substring-before
(concat(substring-after(.,'/'), '/'),
'/'
),
'_',
' '
)
)
"/>
<xsl:template match="/*">
<ul>
<xsl:apply-templates mode="cat" select=
"*/name
[generate-id()
=
generate-id(key('kCatFromName',
substring-before(concat(.,'/'), '/')
)[1]
)
]
"/>
</ul>
</xsl:template>
<xsl:template match="name" mode="cat">
<xsl:variable name="vCat" select=
"substring-before(concat(.,'/'), '/')"/>
<li><xsl:value-of select="$vCat"/></li>
<xsl:variable name="vInThisCat" select=
"key('kCatFromName', $vCat)
[generate-id()
=
generate-id(key('kValFromName',
concat(substring-before(.,'/'),
'+',
translate(
substring-before
(concat(substring-after(.,'/'), '/'),
'/'
),
'_',
' '
)
)
)[1]
)
]"/>
<xsl:if test="$vInThisCat">
<ul>
<xsl:apply-templates mode="val" select="$vInThisCat"/>
</ul>
</xsl:if>
</xsl:template>
<xsl:template match="name" mode="val">
<li>
<xsl:value-of select=
"translate(substring-before
(concat(substring-after(.,'/'), '/'),
'/'
),
'_',
' '
)
"/>
</li>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档:
<table>
<col>
<name>Addresses</name>
</col>
<col>
<name>Addresses/Address1</name>
</col>
<col>
<name>Addresses/Address2</name>
</col>
<col>
<name>Addresses/Address1/Flat Number</name>
</col>
<col>
<name>Employee Name</name>
</col>
<col>
<name>Phone Number</name>
</col>
<col>
<name>Profession</name>
</col>
<col>
<name>Employee Name/First Name</name>
</col>
<col>
<name>Employee Name/Last Name</name>
</col>
<col>
<name>Employee Name/First_Name</name>
</col>
<col>
<name>Accounts/Account Name/First/Saving</name>
</col>
<col>
<name>Accounts/Account_Name/Second</name>
</col>
</table>
生成想要的正确结果:
<ul>
<li>Addresses</li>
<ul>
<li>Address1</li>
<li>Address2</li>
</ul>
<li>Employee Name</li>
<ul>
<li>First Name</li>
<li>Last Name</li>
</ul>
<li>Phone Number</li>
<li>Profession</li>
<li>Accounts</li>
<ul>
<li>Account Name</li>
</ul>
</ul>
,浏览器将其显示为: