我编写了一个 XSLT 代码来获取员工和经理的层次结构,该代码按预期工作,但处理 50,000 条记录大约需要 3 小时。 我相信这是由于创建变量时的循环所致,
尝试优化但尚未找到好的解决方案,任何帮助将不胜感激。
谢谢你。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- Identity template to copy the entire XML structure -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- Template to generate the list of managers per employee -->
<xsl:template match="employee">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<managers>
<xsl:call-template name="findManagers">
<xsl:with-param name="employeeName" select="EmployeePositionID"/>
</xsl:call-template>
</managers>
</xsl:copy>
</xsl:template>
<!-- Template to recursively find managers -->
<xsl:template name="findManagers">
<xsl:param name="employeeName"/>
<xsl:param name="level" select="1"/>
<xsl:if test="$employeeName != ''">
<xsl:variable name="manager" select="//employee[EmployeePositionID = $employeeName]/Manager"/>
<xsl:variable name="ManagerID_Var" select="//employee[EmployeePositionID = $employeeName]/Manager/@personid"/>
<xsl:if test="$manager != ''">
<hierarchy>
<xsl:attribute name="BottomToplevel">
<xsl:value-of select="$level"/>
</xsl:attribute>
<xsl:attribute name="ManagerID">
<xsl:value-of select="$ManagerID_Var"/>
</xsl:attribute>
<xsl:value-of select="$manager"/>
</hierarchy>
<!-- Recursively call the template for the next manager -->
<xsl:call-template name="findManagers">
<xsl:with-param name="employeeName" select="$manager"/>
<xsl:with-param name="level" select="$level + 1"/>
</xsl:call-template>
</xsl:if>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
性能不佳将是因为指令的原因
<xsl:variable name="manager"
select="//employee[EmployeePositionID = $employeeName]/Manager"/>
<xsl:variable name="ManagerID_Var"
select="//employee[EmployeePositionID = $employeeName]/Manager/@personid"/>
这意味着对于每个员工,您都在搜索整个文件以找到该员工的经理,从而使绩效与员工数量成二次方 - O(n^2)。
一些 XSLT 处理器(例如我公司的 Saxon-EE)可能会优化此类表达式以使用索引,但大多数都会对文档进行串行搜索。
但是,您可以“手动”进行索引,这将大大提高性能。像这样定义一个索引:
<xsl:key name="empIndex" match="employee" use="EmployeePositionID"/>
并将
//employee[EmployeePositionID = $employeeName]
替换为 key('empIndex', $employeeName)
。
您还应该能够通过仅搜索一次而不是两次来实现节省:第二个变量可以根据第一个变量定义为
<xsl:variable name="ManagerID_Var"
select="$manager/@personid"/>