1

別のテンプレートの特定の要素に適用される特定のステートメントを分離しました。
要素は、 statement を含む 1 つのテンプレートで処理されます<xsl:apply-templates/>
最初のテンプレートで処理されたばかりの要素を、2 番目の (名前のない) テンプレートで再処理する方法はありますか?
もちろん、名前付きテンプレートを使用して最初のテンプレートから呼び出すことができることは知っていますが、このようにできるかどうかは疑問です。作業するものを提供するために、私が取り組んでいるものの非常に単純化されたモデルを次に示します。
テーブルを含む html 入力ファイルがあります。

<?xml version="1.0" encoding="UTF-8"?>
<table>
    <tbody>
        <tr>
            <td>content</td>
            <td></td>
            <td/>
        </tr>
    </tbody>
</table>

block各要素内に、文字列コンテンツがある場合はtdそれを囲む要素、または要素自体が空の場合は空である要素が必要です。私は次のことを試しました (最初のテンプレートに大きな変更を加えたくないことに注意してください!):tdtd

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

    <xsl:template match="*">
        <xsl:copy>
            <xsl:attribute name="test"><xsl:value-of select="local-name()"/></xsl:attribute>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="td/text()">
        <block><xsl:value-of select="."/></block>
    </xsl:template>
</xsl:stylesheet>

追加された属性は、最初のテンプレートで行われていることのモデル化された例にすぎません。

出力として与える

<?xml version="1.0" encoding="UTF-8"?>
<table test="table">
    <tbody test="tbody">
        <tr test="tr">
            <td test="td">
                <block>content</block>
            </td>
            <td test="td"/>
            <td test="td"/>
        </tr>
    </tbody>
</table>

そして私は手に入れたい

<?xml version="1.0" encoding="UTF-8"?>
<table test="table">
    <tbody test="tbody">
        <tr test="tr">
            <td test="td">
                <block>content</block>
            </td>
            <td test="td">
                <block/>
            </td>
            <td test="td">
                <block/>
            </td>
        </tr>
    </tbody>
</table>

機能しなかった理由は明らかです。空のtd要素にはテキスト ノードがないため、これらは 2 番目のテンプレートの Xpath 式と一致しません。そこで、2 番目のテンプレートで要素自体
を再処理する方法を考え始めました。tdもちろん、match="td[some condition]"最初のテンプレートが適用されないため、使用できません。
また、テンプレートの一致属性で軸が許可されていないmatch= "self::td"ためself(もちろん条件を除いて)、使用できません。または、一致を開始するときにまだ持っていない現在のノードが必要です。
2 番目のテンプレートで使用できる適切な Xpath 式はありますか?
または、1 つのテンプレートで処理されたばかりの要素に対して別の (名前のない) テンプレートをトリガーする別の簡単な方法はありますか?
注: 属性を追加する 2 番目のテンプレートの単純な更新を探しているわけではありません。最初のテンプレートで属性を追加し、2 番目のテンプレートでブロック要素を追加したいと考えています。

4

4 に答える 4

2

xsl:next-matchXSLT2.0またはXSLT1.0で見てくださいxsl:apply-imports

于 2012-04-20T16:13:14.003 に答える
2

別の「モード付き」テンプレートを追加してみてください。xsl:apply-templatesモードで使用できるはずです。

例 xsl:テンプレート:

<xsl:template match="td" mode="test">
  <bar>test</bar>
</xsl:template>

例 xsl:apply-templates:

<xsl:template match="td">
  <foo><xsl:apply-templates select="ancestor-or-self::td" mode="test"/></foo>
</xsl:template>
于 2012-04-20T18:21:53.497 に答える
1

を使用する XSLT 1.0 ソリューション<xsl:apply-imports>

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

    <xsl:import href="block.xsl" />

    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

    <xsl:template match="*">
        <xsl:copy>
            <xsl:attribute name="test"><xsl:value-of select="local-name()"/></xsl:attribute>
            <xsl:if test="self::td">
                <xsl:apply-imports/>
            </xsl:if>  
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

インポートされたスタイルシートblock.xsl :

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

    <xsl:template match="td">
        <block><xsl:value-of select="."/></block>
    </xsl:template>

</xsl:stylesheet>

以下を使用する XSLT 2.0 ソリューション<xsl:next-match>:

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

    <xsl:template match="*">
        <xsl:copy>
            <xsl:attribute name="test"><xsl:value-of select="local-name()"/></xsl:attribute>
            <xsl:if test="self::td">
                <!--apply the next template that would match this td element -->
                <xsl:next-match/>
            </xsl:if>  
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

    <!--calculated priority of "td" would be higher than "*",
        so explicitly setting a lower priority -->
    <xsl:template match="td" priority="-1">
        <block><xsl:value-of select="."/></block>
    </xsl:template>

</xsl:stylesheet>
于 2012-04-20T23:51:28.467 に答える
0

完全を期すために、DevNullの回答によって到達したソリューションを追加します。

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

    <xsl:template match="*">
        <xsl:copy>
            <xsl:attribute name="test"><xsl:value-of select="local-name()"/></xsl:attribute>
            <xsl:apply-templates/>
            <xsl:apply-templates mode="td" select="self::td"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="td" mode="td">
        <block><xsl:value-of select="."/></block>
    </xsl:template>

    <xsl:template match="td/text()"/>
</xsl:stylesheet>

その結果、

<?xml version="1.0" encoding="UTF-8"?>
<table test="table">
    <tbody test="tbody">
        <tr test="tr">
            <td test="td">
                <block>content</block>
            </td>
            <td test="td">
                <block></block>
            </td>
            <td test="td">
                <block></block>
            </td>
        </tr>
    </tbody>
</table>

デフォルトのテンプレートでtdテキストノードが2回処理されないように、追加されたテンプレートに注意してください。

于 2012-04-20T18:53:51.760 に答える