正如原来问题的楼主所说:preceding-sibling是指在上下文节点在原XML文档中的前驱节点集合。所以在mode b中的代码:
<
xsl:if
test=
"not(preceding-sibling::*[@f2=current()/@f2])"
>
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
是判断在此之前没有出现过相同的f2,用preceding-sibling没错,但是这里有一个前提条件:同一个f1,在原文件中如果当前节点存在一个相同的f2,但不是同一个f1,那么当前节点的f2将无法输出了。
如果说f2(代表的是城市)很难有同名的,但是mode c呢,
<
xsl:if
test=
"not(preceding-sibling::*[@f3=current()/@f3])"
>
f3同名的多了吧,更何况,有没有同名的城市还很难说呢。
总之为了程序的严密性,我们必须将其改成:
<
?xml version='1.0'?
>
<
xsl:stylesheet
version=
"1.0"
xmlns:xsl=
"http://www.w3.org/1999/XSL/Transform"
>
<
xsl:template
match=
"/"
>
<
xsl:apply-templates
select=
"root/item"
mode=
"a"
>
<
xsl:sort
select=
"@f1"
/
>
<
/xsl:apply-templates
>
<
/xsl:template
>
<
xsl:template
match=
"item"
mode=
"a"
>
<
xsl:if
test=
"not(preceding-sibling::*[@f1=current()/@f1])"
>
<
xsl:value-of
select=
"concat(@f1,'-')"
/
>
<
xsl:variable
name=
"f1"
select=
"@f1"
/
>
<
xsl:for-each
select=
".."
>
<
xsl:apply-templates
select=
"item[@f1 = $f1]"
mode=
"b"
>
<
xsl:sort
select=
"@f2"
/
>
<
/xsl:apply-templates
>
<
/xsl:for-each
>
<
br/
>
<
/xsl:if
>
<
/xsl:template
>
<
xsl:template
match=
"item"
mode=
"b"
>
<
xsl:if
test=
"not(preceding-sibling::*[@f1=current()/@f1][@f2=current()/@f2])"
>
<
xsl:value-of
select=
"concat(' ',@f2,':')"
/
>
<
xsl:variable
name=
"f2"
select=
"@f2"
/
>
<
xsl:for-each
select=
".."
>
<
xsl:apply-templates
select=
"item[@f2 = $f2]"
mode=
"c"
>
<
xsl:sort
select=
"@f3"
/
>
<
/xsl:apply-templates
>
<
/xsl:for-each
>
<
/xsl:if
>
<
/xsl:template
>
<
xsl:template
match=
"item"
mode=
"c"
>
<
xsl:if
test=
"not(preceding-sibling::*[@f1=current()/@f1][@f2=current()/@f2][@f3=current()/@f3])"
>
<
xsl:if
test=
"position()!=1"
>
<
xsl:value-of
select=
"','"
/
>
<
/xsl:if
>
<
xsl:value-of
select=
"@f3"
/
>
<
/xsl:if
>
<
/xsl:template
>
<
/xsl:stylesheet
>
其实,最重要的一点就是清楚程序每个步骤执行的状态,并有一个清晰的模型,到底是在原
XML
文档,还是节点集合。
转载于:https://blog.51cto.com/electiger/16818