XSLT和XQuery分析器
XSLT/XQuery 分析器是一个用于分析XMLSpy中的XSLT(1.0和2.0)样式表和XQuery文档的执行时间的工具。它会提供XSLT样式表或XQuery文档中的每条指令需要多少时间来执行,您可以利用这一信息来优化这些文件的执行时间。
分析器用于查找总执行时间最长的指令,以便随后可以利用这一信息来优化这些指令。由于以下原因,指令的总执行时间可能很长:
•指令耗时
•经常评估指令(高调用次数)
调用次数和调用图分析
分析器允许您在调用次数和调用图分析之间进行选择。这两种类型的分析都显示了每条指令的执行时间统计信息。
出于优化目的,用户通常使用调用次数分析,它在分析器中为每条指令显示一行。
调用图分析显示XSLT转换或XQuery执行的整个执行历史,即在转换期间调用了哪些模板/函数以及调用的顺序。在调用图分析的结果中,每次调用一条指令都有一行,而不是每条指令一行。
要使用XSLT/XQuery分析器,请参见XSLT分析或XQuery分析。
分析器视图
通过单击相应的选项卡,可以在以下任一视图中查看分析结果:
•列表视图:分析统计信息显示为一个列表,可以按指令的执行时间或指令及其后代的执行时间进行排序。

•树视图:统计信息以树状结构显示,可以查看执行一个函数所用的时间,然后展开该函数的树并查看执行函数中的每条指令所用的时间,以及执行次数。

结果排序
在运行分析器后,您可以按执行指令所用的时间或指令调用次数进行排序。
要在分析器中对信息进行排序,请执行以下操作:
1. | 单击列表选项卡。 |
2. | 单击您想要排序的列的列标题(例如,调用次数,按指令调用次数排序,或执行时间,按指令的执行时间排序)。 |
下方截图显示了分析器的内容,按指令的执行时间降序排序。

优化XSLT样式表和XQuery文档
在优化XSLT样式表和XQuery文档中指令的执行时间时,请牢记以下规则:
•如果变量仅使用一次,请避免在指令中使用变量,因为初始化变量可能很耗时。
以下的XSLT代码片段显示了如何通过删除不必要的变量来优化代码。两个代码片段都做同样的事情,但第二个示例没有使用变量name和containsResult: |
代码片段1: |
<xsl:for-each select="row">
<xsl:variable name="row" select="."/>
<xsl:for-each select="@name">
<xsl:variable name="name" select="."/>
<xsl:variable name="containsResult" select="fn:contains(\$name, '.exe')"/>
<xsl:if test="string(\$containsResult)='true'">
...
</xsl:if>
</xsl:for-each>
</xsl:for-each>
下方截图显示了包含此代码片段的文件的分析结果,按指令的执行时间排序。初始化containsResult变量的指令需要大约19秒的总执行时间。

下方截图显示了树视图中的结果。在这里我们可以看到使用containsResult变量的if语句需要大约50秒的总执行时间:

XSLT转换总共需要大约74秒:

代码片段2: |
<xsl:for-each select="row">
<xsl:variable name="row" select="."/>
<xsl:for-each select="@name">
<xsl:if test="fn:contains(., '.exe')">
...
</xsl:if>
</xsl:for-each>
</xsl:for-each>
在不使用这些变量的情况下重写样式表后,其总执行时间仅约4.3秒。

•如果重复使用值或表达式,请使用变量。
•避免在函数内创建局部常量变量;改为创建全局变量。
•避免在函数内创建常量树片段;改为将其创建为全局。
•避免使用谓词,因为谓词过滤是针对每个节点单独评估的。您可以减少对谓词的调用次数,例如,通过使用名称进行预过滤。在本例中,*与两个谓词一起使用:
//*[node-name()=Book][author="Steve"]
在这个等价的语句中,使用了Book名称和仅一个谓词: |
//Book[@Author="Steve"]
•拆分指令,使得仅需要执行一次的部分指令仅执行一次。从仅依赖于全局上下文的部分创建全局变量。