3

私は xsl DRY を維持しようとしています。その結果、たまたま同じ複合型 (ContactDetails と AltContactDetails) である XML ドキュメントの 2 つのセクションに対して同じテンプレートを呼び出したいと思いました。次の XML があるとします。

<?xml version="1.0" encoding="UTF-8"?>
<RootNode>
    <Name>Bob</Name>
    <ContactDetails>
        <Address>
            <Line1>1 High Street</Line1>
            <Town>TownName</Town>
            <Postcode>AB1 1CD</Postcode>
        </Address>
        <Email>test@test.com</Email>
    </ContactDetails>
    <AltContactDetails>
        <Address>
            <Line1>3 Market Square</Line1>
            <Town>TownName</Town>
            <Postcode>EF2 2GH</Postcode>
        </Address>
        <Email>bob@bob.com</Email>
    </AltContactDetails>
</RootNode>

次のように 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="/">
        <PersonsName>
            <xsl:value-of select="RootNode/Name"/>
        </PersonsName>
        <xsl:call-template name="ContactDetails">
            <xsl:with-param name="data"><xsl:value-of select="RootNode/ContactDetails"/></xsl:with-param>
            <xsl:with-param name="elementName"><xsl:value-of select="'FirstAddress'"/></xsl:with-param>
        </xsl:call-template>
        <xsl:call-template name="ContactDetails">
            <xsl:with-param name="data"><xsl:value-of select="RootNode/AltContactDetails"/></xsl:with-param>
            <xsl:with-param name="elementName"><xsl:value-of select="'SecondAddress'"/></xsl:with-param>
        </xsl:call-template>
    </xsl:template>
    <xsl:template name="ContactDetails">
        <xsl:param name="data"></xsl:param>
        <xsl:param name="elementName"></xsl:param>
        <xsl:element name="{$elementName}">
            <FirstLine>
                <xsl:value-of select="$data/Address/Line1"/>
            </FirstLine>

            <Town>
                <xsl:value-of select="$data/Address/Town"/>
            </Town>
            <PostalCode>
                <xsl:value-of select="$data/Address/Postcode"/>
            </PostalCode>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

スタイルシートを実行しようとすると、次のことが必要だと不平を言っています。

パス式で結果ツリー フラグメントを使用するには、exsl:node-set() を使用するか、バージョン 1.1 を指定します。

バージョン 1.1 には行きたくないので、上記の例で exsl:node-set() を機能させる方法を知っている人はいますか?

または、誰かが同じテンプレートを 2 つの異なるセクションに適用するためのより良い方法を知っていれば、それも本当に役に立ちますか?

ありがとう

デイブ

4

2 に答える 2

9

あなたはこれを間違った方向から巻き上げています (間違った方向はほとんどの場合、命令型プログラミング パラダイムを XSLT に適用しようとしています)。

これは、テンプレート マッチングを使用して行うのは非常に簡単です。

<xsl:template match="RootNode">
  <PersonsName>
    <xsl:value-of select="Name"/>
  </PersonsName>
  <xsl:apply-templates select="ContactDetails|AltContactDetails" />
</xsl:template>

<xsl:template match="ContactDetails|AltContactDetails">
  <xsl:copy>
    <FirstLine>
      <xsl:value-of select="Address/Line1"/>
    </FirstLine>
    <Town>
      <xsl:value-of select="Address/Town"/>
    </Town>
    <PostalCode>
      <xsl:value-of select="Address/Postcode"/>
    </PostalCode>
  </xsl:copy>
</xsl:template>

XSLT プロセッサに何をすべきかを伝える必要があるという考えは捨ててください (名前付きテンプレートを作成し、それらを「命令型スタイル」で呼び出すことによって)。

XSLT プロセッサは、呼び出すテンプレートを選択します。ルート ( /) から開始して、アクセスするすべてのノードの一致するテンプレートを再帰的にチェックします。入力 XML をすべて単独でトラバースします。唯一の仕事は、特別な方法で処理したいノードに一致するテンプレートを提供することです。

特別な処理が必要なノード用のカスタム テンプレートをドロップインし、XSLT プロセッサが起動したらそれを呼び出すことを信頼できます。テンプレートで確認する必要があるのは、適切な<xsl:apply-templates />.

于 2010-03-24T17:16:47.273 に答える
2

テンプレートを作らない理由

<xsl:template match="ContactDetails|AltContactDetails">

代わりに、テンプレート内の出力要素名を決定するテストを行いますか?

于 2010-03-24T17:11:12.313 に答える