Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Optimization 优化<;xsl:choose>;有很多<;xsl:when>;_Optimization_Xslt - Fatal编程技术网

Optimization 优化<;xsl:choose>;有很多<;xsl:when>;

Optimization 优化<;xsl:choose>;有很多<;xsl:when>;,optimization,xslt,Optimization,Xslt,我有一系列中型XML文档,主要是文本,有几个节点表示要扩展的宏,例如: <foo>Some text <macro>A1</macro> ... <macro>B2</macro> ...etc...</foo> 一些文本A1。。。B2……等等。。。 我的目标是用相应的XML替换每个宏。通常它是一个带有不同属性的标记,但也可以是其他HTML 样式表是通过编程生成的,其中一种方法是为每个宏创建一个模板,例如 <xsl

我有一系列中型XML文档,主要是文本,有几个节点表示要扩展的宏,例如:

<foo>Some text <macro>A1</macro> ... <macro>B2</macro> ...etc...</foo>
一些文本A1。。。B2……等等。。。
我的目标是用相应的XML替换每个宏。通常它是一个带有不同属性的
标记,但也可以是其他HTML

样式表是通过编程生成的,其中一种方法是为每个宏创建一个模板,例如

<xsl:template match="macro[.='A1']">
    <!-- content goes here -->
</xsl:template>
<xsl:template match="macro[.='A2']">
    <!-- other content goes here -->
</xsl:template>
<xsl:template match="macro[.='B2']">
    <!-- etc... -->
</xsl:template>

它工作得很好,但它最多可以有100个宏,而且性能不太好(我使用的是libxslt)。我尝试了几种替代方法,例如:

<xsl:template match="macro">
    <xsl:choose>
        <xsl:when test=".='A1'">
            <!-- content goes here -->
        </xsl:when>
        <xsl:when test=".='A2'">
            <!-- other content goes here -->
        </xsl:when>
        <xsl:when test=".='B2'">
            <!-- etc... -->
        </xsl:when>
    </xsl:choose>
</xsl:template>

它的性能稍微好一点。我已尝试添加另一级别的分支,例如:

<xsl:template match="macro">
    <xsl:choose>
        <xsl:when test="substring(.,1,1) = 'A'">
            <xsl:choose>
                <xsl:when test=".='A1'">
                    <!-- content goes here -->
                </xsl:when>
                <xsl:when test=".='A2'">
                    <!-- other content goes here -->
                </xsl:when>
            </xsl:choose>
        </xsl:when>
        <xsl:when test=".='B2'">
            <!-- etc... -->
        </xsl:when>
    </xsl:choose>
</xsl:template>

它的加载速度稍慢(XSL更大,更复杂),但执行速度稍快(每个分支可以消除几种情况)

现在我想知道,有没有更好的方法?我有大约50-100个宏。通常,转换是使用libxslt执行的,但我不能使用其他XSLT引擎的专有扩展


欢迎任何输入:)

如果您的宏是固定的XML,您可以有一个类似以下内容的
macros.XML
文档:

<?xml version="1.0"?>
<macros>
    <macro name="A1"><!-- content goes here --></macro>
    <macro name="A2"><!-- content goes here --></macro>
</macros>

然后,您可以拥有:

<xsl:template match="macro">
    <xsl:variable name="name" select="text()"/>
    <xsl:apply-templates select="document(macros.xml)/macros/macro[@name=$name]" mode="copy"/>
</xsl:template>

<xsl:template match="*" mode="copy">
    <xsl:copy><xsl:copy-of select="*"/>
        <xsl:apply-templates mode="copy"/>
    </xsl:copy>
</xsl:template>


这会提高性能吗?

如果您的宏是固定的XML,则可以使用类似以下内容的
macros.XML
文档:

<?xml version="1.0"?>
<macros>
    <macro name="A1"><!-- content goes here --></macro>
    <macro name="A2"><!-- content goes here --></macro>
</macros>

然后,您可以拥有:

<xsl:template match="macro">
    <xsl:variable name="name" select="text()"/>
    <xsl:apply-templates select="document(macros.xml)/macros/macro[@name=$name]" mode="copy"/>
</xsl:template>

<xsl:template match="*" mode="copy">
    <xsl:copy><xsl:copy-of select="*"/>
        <xsl:apply-templates mode="copy"/>
    </xsl:copy>
</xsl:template>


这是否提高了性能?

尝试将所有的
处理提取到一个单独的模板模式中,并仅对
元素的内容运行它。即:

<xsl:template match="macro">
   <xsl:apply-templates mode="macro"/>
</xsl:template>

<xsl:temlate match="text()[. = 'A1']" mode="macro">
   ...
</xsl:template>

...

我怀疑您的情况会变慢,因为您的规则会针对输入中的每个节点逐一进行检查。这样,您就可以进行一次检查,查看它是否是一个
,并且只有当它是时,内容才会进一步匹配。

尝试将所有
处理提取到一个单独的模板模式中,并且只对
元素的内容运行它。即:

<xsl:template match="macro">
   <xsl:apply-templates mode="macro"/>
</xsl:template>

<xsl:temlate match="text()[. = 'A1']" mode="macro">
   ...
</xsl:template>

...

我怀疑您的情况会变慢,因为您的规则会针对输入中的每个节点逐一进行检查。通过这种方式,您可以进行一次检查,查看它是否是一个
宏,并且只有当它是宏时,内容才会进一步匹配。

这将是另一种方式:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="xsl">
    <xsl:variable name="dummy">
            <mac id="A1">success</mac>
            <mac id="A2">fail</mac>
            <mac id="B1">This <b>fail</b></mac>
            <mac id="B2">This <b>success</b></mac>
    </xsl:variable>
    <xsl:key name="macro" match="mac" use="@id"/>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="macro">
        <xsl:variable name="me" select="."/>
        <xsl:for-each select="document('')">
            <xsl:copy-of select="key('macro',$me)/node()"/>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

成功
失败
这次失败了
这一成功

注意:这就是性能:XML解析1805ms,XSL解析0483ms,转换0215ms

这是另一种方式:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="xsl">
    <xsl:variable name="dummy">
            <mac id="A1">success</mac>
            <mac id="A2">fail</mac>
            <mac id="B1">This <b>fail</b></mac>
            <mac id="B2">This <b>success</b></mac>
    </xsl:variable>
    <xsl:key name="macro" match="mac" use="@id"/>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="macro">
        <xsl:variable name="me" select="."/>
        <xsl:for-each select="document('')">
            <xsl:copy-of select="key('macro',$me)/node()"/>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

成功
失败
这次失败了
这一成功

注意:这就是性能:XML解析1805ms,XSL解析0483ms,转换0215ms

我尝试过
,但性能更差,考虑到它必须访问外部资源并在其上运行一些XPath,这是可以预料的。也许我可以在某个地方用xsl:key再试一次。。。谢谢:)您尝试过将文档加载到变量中并使用它吗?不过,您需要使用扩展来支持变量作为节点集。这将只加载文档一次。我尝试过
,但性能更差,考虑到它必须访问外部资源并在其上运行一些XPath,这是意料之中的。也许我可以在某个地方用xsl:key再试一次。。。谢谢:)您尝试过将文档加载到变量中并使用它吗?不过,您需要使用扩展来支持变量作为节点集。这将只加载一次文档。这种方法的性能与我的第一种方法大致相同,但由于额外的
,会有一点损失。不管怎样,它实际上并不慢,或者至少不比XSL转换预期的慢。libxslt做得不错,我只是想看看是否可以从中挤出更多的性能。这种方法的性能与我的第一种方法大致相同,但由于额外的
,会有一点损失。不管怎样,它实际上并不慢,或者至少不比XSL转换预期的慢。libxslt做得不错,我只是想看看是否可以从中获得更高的性能。奇怪的是,我已经尝试过类似的方法,但没有成功,因为
document(“”)
返回的是源文档的根,而不是样式表的根。我刚刚检查了XSLT规范,事实上,它应该返回样式表的根,这样要么我发现了一个bug,要么我把事情搞砸了。我会再试一次,并保持更新,谢谢。确实,这是一个已知的LIbxSLT错误,我打了()我让它工作,但性能似乎与我列出的第二种方法一致。如果重复使用同一个宏,它的伸缩性似乎更好。奇怪的是,我已经尝试过类似的方法,但没有成功,因为
document(“”)
返回的是源文档的根,而不是样式表的根。我刚刚检查了XSLT规范,事实上,它应该返回样式表的根,这样要么我发现了一个bug,要么我把事情搞砸了。我会再试一次,让你随时了解最新情况,谢谢。的确,这是一个好主意