我正在尝试使用XSL文档对几个级别的数据进行排序。我得到了它的工作,但它使用了一堆递归。我试图避免这种情况,因为我认为使用单个节点的多种排序已经有效。有没有办法将下面的XSL更改为更少的递归?我在USER / USERID上排序,然后是ROLE / @ name,最后是ACTIONINFO / @ actionfrom
工作样式表:
<xsl:template match="/">
<xsl:apply-templates select="USERACTIONINFO"/>
</xsl:template>
<xsl:template match="USERACTIONINFO">
<xsl:copy>
<xsl:for-each select="USER">
<xsl:sort select="USERID"/>
<xsl:copy>
<xsl:copy-of select="USERID" />
<xsl:for-each select="ROLE">
<xsl:sort select="@name"/>
<xsl:copy>
<xsl:copy-of select="@name" />
<xsl:apply-templates select="ACTIONINFO">
<xsl:sort select="@actionfrom"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:for-each>
</xsl:copy>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="*|@*|text()">
<xsl:copy>
<xsl:apply-templates select="*|@*|text()">
</xsl:apply-templates>
</xsl:copy>
</xsl:template
</xsl:stylesheet>
要测试的一些XML:
<USERACTIONINFO >
<USER>
<USERID>SSSUSER</USERID>
<ROLE name="ZZ_UPD">
<ACTIONINFO actionfrom="ZC" />
<ACTIONINFO actionfrom="AC" />
</ROLE>
<ROLE name="QQ_UPD">
<ACTIONINFO actionfrom="AZCC11" />
<ACTIONINFO actionfrom="ACC11" />
</ROLE>
</USER>
<USER>
<USERID>AAAUSER</USERID>
<ROLE name="PP_UPD">
<ACTIONINFO actionfrom="ZZADBENF" />
</ROLE>
<ROLE name="PP_BOEE">
<ACTIONINFO actionfrom="BOM02" />
</ROLE>
<ROLE name="PP_SS">
<ACTIONINFO actionfrom="AZDBENF" />
<ACTIONINFO actionfrom="ADDBEN" />
</ROLE>
</USER>
</USERACTIONINFO>
实际正确输出:
<USERACTIONINFO>
<USER>
<USERID>AAAUSER</USERID>
<ROLE name="PP_BOEE">
<ACTIONINFO actionfrom="BOM02" />
</ROLE>
<ROLE name="PP_SS">
<ACTIONINFO actionfrom="ADDBEN" />
<ACTIONINFO actionfrom="AZDBENF" />
</ROLE>
<ROLE name="PP_UPD">
<ACTIONINFO actionfrom="ZZADBENF" />
</ROLE>
</USER>
<USER>
<USERID>SSSUSER</USERID>
<ROLE name="QQ_UPD">
<ACTIONINFO actionfrom="ACC11" />
<ACTIONINFO actionfrom="AZCC11" />
</ROLE>
<ROLE name="ZZ_UPD">
<ACTIONINFO actionfrom="AC" />
<ACTIONINFO actionfrom="ZC" />
</ROLE>
</USER>
</USERACTIONINFO>
我认为我应该能够做但却无法工作:
<xsl:stylesheet version='1.0'
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:output omit-xml-declaration="yes"/>
<xsl:template match="/">
<xsl:apply-templates select="USERACTIONINFO"/>
</xsl:template>
<xsl:template match="USERACTIONINFO">
<xsl:copy>
<xsl:apply-templates select="USER">
<xsl:sort select="USERID"/>
<xsl:sort select="ROLE/@name"/>
<xsl:sort select="ROLE/ACTIONINFO/@actionfrom"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="*|@*|text()">
<xsl:copy>
<xsl:apply-templates select="*|@*|text()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
答案 0 :(得分:2)
我不确定你为什么要这么努力。 <xsl:apply-templates>
为您完成所有必要的迭代。您根本不使用(或需要)任何递归。只是不要使用嵌套<xsl:for-each>
三层深度的东西来对付它。
单独的专用模板更易于阅读和维护:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<!-- in USERACTIONINFO: output USER sorted by USERID -->
<xsl:template match="USERACTIONINFO">
<xsl:copy>
<xsl:apply-templates select="USER">
<xsl:sort select="USERID" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<!-- in USER: output ROLE sorted by @name -->
<xsl:template match="USER">
<xsl:copy>
<xsl:copy-of select="USERID" />
<xsl:apply-templates select="ROLE">
<xsl:sort select="@name" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<!-- in ROLE: output ACTIONINFO sorted by @actionfrom -->
<xsl:template match="ROLE">
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:apply-templates select="ACTIONINFO">
<xsl:sort select="@actionfrom" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<!-- output ACTIONINFO verbatim -->
<xsl:template match="ACTIONINFO">
<xsl:copy-of select="." />
</xsl:template>
</xsl:stylesheet>
结果符合要求:
<USERACTIONINFO>
<USER>
<USERID>AAAUSER</USERID>
<ROLE name="PP_BOEE">
<ACTIONINFO actionfrom="BOM02" />
</ROLE>
<ROLE name="PP_SS">
<ACTIONINFO actionfrom="ADDBEN" />
<ACTIONINFO actionfrom="AZDBENF" />
</ROLE>
<ROLE name="PP_UPD">
<ACTIONINFO actionfrom="ZZADBENF" />
</ROLE>
</USER>
<USER>
<USERID>SSSUSER</USERID>
<ROLE name="QQ_UPD">
<ACTIONINFO actionfrom="ACC11" />
<ACTIONINFO actionfrom="AZCC11" />
</ROLE>
<ROLE name="ZZ_UPD">
<ACTIONINFO actionfrom="AC" />
<ACTIONINFO actionfrom="ZC" />
</ROLE>
</USER>
</USERACTIONINFO>
答案 1 :(得分:0)
不,你不能。
你意识到你的代码
<xsl:apply-templates select="USER">
<xsl:sort select="USERID"/>
<xsl:sort select="ROLE/@name"/>
</xsl:apply-templates>
产生了负面意义,因为它建议您按照角色名称对用户ID进行排序?
说真的,当你在USER上应用模板时,你会对用户进行排序,而不是对用户进行排序。如果它采取其他行动,那就太棒了。
所以不,你应该坚持完全合法的第一个例子。
您可以将其分解为几个模板,从而使其更长,但不那么深,等等。