在我的场景中最好的 XSLT XPath 性能是什么?

What is best XSLT XPath performance in my scenario?

我对 XSLT XPath 性能有疑问。如果我们看下面的例子。

以下哪个选项的性能最佳:

<xsl:for-each select="//cd">

<xsl:for-each select="//catalog/cd">

XML数据:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <catalog>
        <cd>
            <title>Empire Burlesque</title>
            <artist>Bob Dylan</artist>
        </cd>
        <cd>
            <title>Hide your heart</title>
            <artist>Bonnie Tyler</artist>
        </cd>
    </catalog>
    <catalog>
        <cd>
            <title>Greatest Hits</title>
            <artist>Dolly Parton</artist>
        <cd>
            <title>Still got the blues</title>
            <artist>Gary Moore</artist>
        </cd>
    </catalog>
</root>

XSLT 样式表:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
  <html>
  <body>
    <h2>My CD Collection</h2>
    <table border="1">
      <tr bgcolor="#9acd32">
        <th>Title</th>
        <th>Artist</th>
      </tr>
      <xsl:for-each select="//cd">
      <tr>
        <td><xsl:value-of select="title" /></td>
        <td><xsl:value-of select="artist" /></td>
      </tr>
      </xsl:for-each>
    </table>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>

哪个性能最好?

(我让这个更小更简单的例子,在我的真实案例中我有更复杂的数据结构)

首先,您的输入文档格式不正确; cd 元素之一未闭合,并且没有包含其他所有元素的单个最外层元素。假设输入如下:

XML 输入

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <catalog>
        <cd>
            <title>Empire Burlesque</title>
            <artist>Bob Dylan</artist>
        </cd>
        <cd>
            <title>Hide your heart</title>
            <artist>Bonnie Tyler</artist>
        </cd>
    </catalog>
    <catalog>
        <cd>
            <title>Greatest Hits</title>
            <artist>Dolly Parton</artist>
        </cd>
        <cd>
            <title>Still got the blues</title>
            <artist>Gary Moore</artist>
        </cd>
    </catalog>
</root>

现在,关于您的问题:您不应使用 <xsl:for-each select="//cd"><xsl:for-each select="//catalog/cd">。事实上,你根本不应该使用 xsl:for-each,这里没有理由使用它。你最好学习如何编写单独的模板来完成这项工作,就像下面的样式表一样。

XSLT 样式表

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="html" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/root">
      <html>
      <body>
        <h2>My CD Collection</h2>
        <table border="1">
          <tr bgcolor="#9acd32">
            <th>Title</th>
            <th>Artist</th>
          </tr>
          <xsl:apply-templates/>
        </table>
      </body>
      </html>
    </xsl:template>

    <xsl:template match="cd">
        <tr>
            <xsl:apply-templates/>
        </tr>
    </xsl:template>

    <xsl:template match="title|artist">
        <td>
            <xsl:value-of select="."/>
        </td>
    </xsl:template>

</xsl:stylesheet>

虽然输出确实完全相同并且可以使用 xsl:for-each,但 for-each 是一个过度使用的构造,尤其是对于初学者 - 在模板本来可以使用更多的地方优雅。


Wich has the best performance?

此问题与 XSLT 无关,与 XSLT 中嵌入的 XPath 表达式有关:

<xsl:for-each select="//cd">
^^^^^^^^^^^^^^^^^^^^^^    ^^      XSLT
                      ^^^^        XPath

通常,XPath 表达式应该避开 // (descendant-or-self::) 轴。您应该始终不愿意使用 //,并且只有在输入文档的结构确实不可预测或者您想要定位的元素是任意嵌套的情况下才使用它。

这个问题唯一可能的答案是 "it depends on the processor"。通常,您应该避免不必要地使用 //,但聪明的处理器可能能够优化简单的 //something 绝对路径(例如,使用散列 table 按名称查找节点)比完全指定的 /root/catalog/cd.

更快

您必须根据您的特定数据分析您的特定处理器。

测量一下看看。在您拥有适当的测量框架之前,您甚至不应该开始研究提高性能的方法。如果您有适当的衡量框架,则无需在此处提出问题,如果没有,则无法评估答案。