我想应用一个XSL样式表来计算以前唯一的“ROLE”节点,并吐出以下输出格式的ROLE / @ name,PERM / @ perfrom以及当前节点之前的唯一ROLE节点数。
这是this question的延续,但复杂程度更高。我相信Muenchian方法是实现此方法的最佳方法,因为此文件的长度很大。
我有以下XML(抱歉长度)
<?xml version="1.0" encoding="utf-8" ?>
<ROLEACTIONINFO>
<ROLE name="TESTER">
<ACTIONINFO>
<PERMINFO>
<PERM type="PT0" field="ALL" permfrom="PERM1565"/>
</PERMINFO>
</ACTIONINFO>
</ROLE>
<ROLE name="PARENT1">
<ACTIONINFO>
</ACTIONINFO>
</ROLE>
<ROLE name="PARENT1">
<ACTIONINFO>
<PERMINFO>
<PERM type="PT8" field="ALL" permfrom="PERM1"/>
</PERMINFO>
</ACTIONINFO>
</ROLE>
<ROLE name="PARENT1">
<ACTIONINFO>
<PERMINFO>
<PERM type="PT7" field="ALL" permfrom="PERM2"/>
<PERM type="PT7" field="ALL" permfrom="PERM54"/>
</PERMINFO>
</ACTIONINFO>
</ROLE>
<ROLE name="PARENT2">
<ACTIONINFO>
<PERMINFO>
<PERM type="PT6" field="ALL" permfrom="PERM1"/>
</PERMINFO>
</ACTIONINFO>
</ROLE>
<ROLE name="PARENT2">
<ACTIONINFO>
<PERMINFO>
<PERM type="PT5" field="ALL" permfrom="PERM2"/>
</PERMINFO>
</ACTIONINFO>
</ROLE>
<ROLE name="PARENT3">
<ACTIONINFO>
<PERMINFO>
<PERM type="PT2" field="ALL" permfrom="PERM44"/>
</PERMINFO>
</ACTIONINFO>
</ROLE>
</ROLEACTIONINFO>
这是我一直在玩的版本XSL表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="text()"/>
<xsl:key name="kRole" match="ROLE[ACTIONINFO/PERMINFO/PERM]" use="@name" />
<xsl:template match="PERM">
<xsl:variable name="roles-so-far" select="ancestor::ROLE | ancestor::ROLE/preceding-sibling::ROLE[ACTIONINFO/PERMINFO/PERM]"/>
<!-- Only select the first instance of each ROLE name -->
<xsl:variable name="roles-so-far-unique"
select="$roles-so-far[generate-id(ancestor::ROLE) = generate-id(key('kRole',ancestor::ROLE/@name)[1])]"/>
<xsl:apply-templates select="ancestor::ROLE/@name"/>
<xsl:text>	</xsl:text>
<xsl:apply-templates select="@permfrom"/>
<xsl:text>	</xsl:text>
<xsl:value-of select="count($roles-so-far-unique)"/>
<!-- linefeed -->
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
这是所需的输出:
TESTER PERM1565 1
PARENT1 PERM1 2
PARENT1 PERM2 2
PARENT1 PERM54 2
PARENT2 PERM1 3
PARENT2 PERM2 3
PARENT3 PERM44 4
这是实际的(不正确的)输出:
TESTER PERM1565 1
PARENT1 PERM1 2
PARENT1 PERM2 3
PARENT1 PERM54 3
PARENT2 PERM1 4
PARENT2 PERM2 5
PARENT3 PERM44 6
提前致谢。
答案 0 :(得分:1)
这来自每个<PERM>
,取相应的<ROLE>
并计算它独特的前辈:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:output method="text" />
<xsl:variable name="TAB" select="'	'" />
<xsl:variable name="LF" select="'
'" />
<xsl:key name="kRole" match="ROLE" use="@name" />
<xsl:template match="/">
<xsl:apply-templates select="//PERM" />
</xsl:template>
<xsl:template match="PERM">
<xsl:variable name="vThisRole" select="ancestor::ROLE[1]" />
<xsl:variable name="vPrecedingRoles" select="
($vThisRole | $vThisRole/preceding-sibling::ROLE)
" />
<xsl:variable name="vUniquePrecedingRoles" select="
$vPrecedingRoles[count(. | key('kRole', ./@name)[1]) = 1]
" />
<xsl:value-of select="
concat(
$vThisRole/@name, $TAB,
@permfrom, $TAB,
count($vUniquePrecedingRoles), $LF
)
" />
</xsl:template>
</xsl:stylesheet>
输出:
TESTER PERM1565 1 PARENT1 PERM1 2 PARENT1 PERM2 2 PARENT1 PERM54 2 PARENT2 PERM1 3 PARENT2 PERM2 3 PARENT3 PERM44 4
如果你问我,你正在处理的XML状况非常糟糕。至少任何安全相关的事实都是由“前面的唯一名称的数量”而不是正确的数据结构来表达,这让我抓狂了。 ;-)你有可能改变输入吗?