1

グローバル変数にバインドする単純な関数と複雑な関数の 2 つの関数があるとします。

<xsl:variable name="a" select="eg:quick-func()"/>
<xsl:variable name="b" select="e.g.:very-long-func()"/>

多くの処理時間を避けるために、$a が true の場合に $b の計算を避けたいと考えています。以下の 3 つのオプション (Saxon 9) をテストすると、$a が true の場合でも $b が計算されることがわかりました。

<xsl:copy-of select="if ($a) then $a else $b"/>

<xsl:copy-of select="($a,$b)[1]"/>

<xsl:choose>
  <xsl:when test="$a">
    <xsl:copy-of select="$a"/>
  </xsl:when>
  <xsl:otherwise>
    <xsl:copy-of select="$b"/>
  </xsl:otherwise>
</xsl:choose>

回避策はありますか?

4

2 に答える 2

1

スタイルシートをテストしました

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:mf="http://example.com/mf"
  exclude-result-prefixes="xs"
  version="2.0">

<xsl:function name="mf:f1" as="node()*">
  <xsl:param name="input"/>
  <xsl:param name="bar"/>
  <xsl:message select="'f1 called'"/>
  <xsl:sequence select="$input//foo[bar = $bar]"/>
</xsl:function>

<xsl:function name="mf:f2" as="node()*">
  <xsl:param name="input"/>
  <xsl:param name="baz"/>
  <xsl:message select="'f2 called'"/>
  <xsl:sequence select="$input//foo[baz = $baz]"/>
</xsl:function>

<xsl:variable name="a" select="mf:f1(/, 'bar 1')"/>
<xsl:variable name="b" select="mf:f2(/, 'baz 1')"/>

<xsl:template match="/">
  <xsl:sequence select="if ($a) then $a else $b"/>
</xsl:template>

</xsl:stylesheet>

入力で

<root>
  <foo>
    <bar>bar 1</bar>
    <baz>baz a</baz>
  </foo>
  <foo>
    <bar>bar 2</bar>
    <baz>baz 1</baz>
  </foo>
</root>

Saxon 9.6 HE を使用し、出力は

f1 called
<?xml version="1.0" encoding="UTF-8"?><foo>
    <bar>bar 1</bar>
    <baz>baz a</baz>
  </foo>

スタイルシートで

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:mf="http://example.com/mf"
  exclude-result-prefixes="xs"
  version="2.0">

<xsl:function name="mf:f1" as="node()*">
  <xsl:param name="input"/>
  <xsl:param name="bar"/>
  <xsl:message select="'f1 called'"/>
  <xsl:sequence select="$input//foo[bar = $bar]"/>
</xsl:function>

<xsl:function name="mf:f2" as="node()*">
  <xsl:param name="input"/>
  <xsl:param name="baz"/>
  <xsl:message select="'f2 called'"/>
  <xsl:sequence select="$input//foo[baz = $baz]"/>
</xsl:function>

<xsl:variable name="a" select="mf:f1(/, 'bar 1')"/>
<xsl:variable name="b" select="mf:f2(/, 'baz 1')"/>

<xsl:template match="/">
  <xsl:sequence select="if ($b) then $b else $a"/>
</xsl:template>

</xsl:stylesheet>

出力は

f2 called
<?xml version="1.0" encoding="UTF-8"?><foo>
    <bar>bar 2</bar>
    <baz>baz 1</baz>
  </foo>

コードを次のように変更すると

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:mf="http://example.com/mf"
  exclude-result-prefixes="xs"
  version="2.0">

<xsl:function name="mf:f1" as="node()*">
  <xsl:param name="input"/>
  <xsl:param name="bar"/>
  <xsl:message select="'f1 called'"/>
  <xsl:sequence select="$input//foo[bar = $bar]"/>
</xsl:function>

<xsl:function name="mf:f2" as="node()*">
  <xsl:param name="input"/>
  <xsl:param name="baz"/>
  <xsl:message select="'f2 called'"/>
  <xsl:sequence select="$input//foo[baz = $baz]"/>
</xsl:function>

<xsl:variable name="a" select="mf:f1(/, 'bar x')"/>
<xsl:variable name="b" select="mf:f2(/, 'baz 1')"/>

<xsl:template match="/">
  <xsl:sequence select="if ($a) then $a else $b"/>
</xsl:template>

</xsl:stylesheet>

次に、両方の関数が呼び出されます。

f1 called
f2 called
<?xml version="1.0" encoding="UTF-8"?><foo>
    <bar>bar 2</bar>
    <baz>baz 1</baz>
  </foo>
于 2015-08-18T17:29:03.860 に答える
0

1 つの方法は、グローバル変数ではなく a および b メモ関数を作成することです。

<function name="f:a" saxon:memo-function="yes">
 <xsl:sequence select="eg:quick-func()"/>
</function>
于 2015-08-19T07:20:37.697 に答える