3

バックグラウンド

HTML を生成する際に、文と文末の句読点の間にスペースを導入する過度の改行を行わずに、読みやすい XSL ソース コードを維持します。XSLT の再考から:

XSLT スタイルシートの空白は、次の 2 つの目的に役立つため、特に問題になります。(1) XSLT スタイルシート自体をフォーマットするため。(2) XSLT 処理された XML データの出力で空白をどこに入れるかを指定するため。

問題

XSL テンプレートには、次のコードが含まれています。

  <xsl:if test="@min-time &lt; @max-time">
    for
    <xsl:value-of select="@min-time" />
    to
    <xsl:value-of select="@max-time" />
    minutes
  </xsl:if>

  <xsl:if test="@setting">
    on <xsl:value-of select="@setting" /> heat
  </xsl:if>
  .

たとえば、これにより次の出力が生成されます (空白は示されているとおりです)。

    for
    2
    to
    3
    minutes
  .

すべての主要なブラウザーは以下を生成します。

for 2 to 3 minutes .

minutes単語と句読点の間のスペースを除いて、ほぼ完璧です。望ましい出力は次のとおりです。

for 2 to 3 minutes.

XSL テンプレート内のインデントと改行を削除してスペースを削除することは可能かもしれませんが、それは XSL ソース コードが醜いことを意味します。

回避策

最初に、目的の出力が変数にラップされ、次のように書き出されました。

<xsl:value-of select="normalize-space($step)" />.

<span>これは、要素を変数にラップしようとするまで機能しました。<span>要素は、生成された HTML コード内に表示されませんでした。次のコードも正しくありません。

<xsl:copy-of select="normalize-space($step)" />.

技術的な詳細

スタイルシートはすでに使用しています:

<xsl:strip-space elements="*" />
<xsl:output indent="no" ... />

関連している

質問

XSLT プロセッサにそのスペースを削除するように指示するにはどうすればよいでしょうか?

ありがとうございました!

4

2 に答える 2

3

を使用する代わりにcopy-of、テキスト ノードからスペースを削除する追加のテンプレートを使用して ID テンプレートを適用できます。最初の回避策のように、変数を 1 つだけ作成します。

あなたが呼ぶ:

<li><xsl:apply-templates select="$step" mode="nospace" />.</li>

テンプレート:

<xsl:template match="text()" mode="nospace" priority="1" >
    <xsl:value-of select="normalize-space(.)" />
</xsl:template>

<xsl:template match="node() | @*" mode="nospace">
    <xsl:copy>
        <xsl:apply-templates select="node() | @*" mode="nospace" />
    </xsl:copy>
</xsl:template>
于 2012-05-14T02:58:28.283 に答える
2

I.この変換:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="t[@max-time > @min-time]">
  <span>
    <xsl:value-of select=
      "concat('for ', @min-time, ' to ', @max-time, ' minutes')"/>
  </span>
  <xsl:apply-templates select="@setting"/>
  <xsl:text>.</xsl:text>
 </xsl:template>

 <xsl:template match="@setting">
  <span>
    <xsl:value-of select="concat(' on ', ., ' heat')"/>
  </span>
 </xsl:template>
</xsl:stylesheet>

次のXMLドキュメントに適用した場合(何も表示されていません!):

<t min-time="2" max-time="3" setting="moderate"/>

必要な正しい結果を生成します。

<span>for 2 to 3 minutes</span>
<span> on moderate heat</span>.

そしてそれはブラウザによって次のように表示されます

適度な熱で2〜3分間。

同じ変換がこのXMLドキュメントに適用される場合

<t min-time="2" max-time="3"/>

ここでも、正しい、必要な結果が生成されます。

<span>for 2 to 3 minutes</span>.

そしてそれはブラウザによって次のように表示されます

2〜3分間。


II。レイアウト(ビジュアル)ソリューション

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my" xmlns:gen="gen:gen" xmlns:gen-attr="gen:gen-attr"
 exclude-result-prefixes="my gen">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <my:layout>
  <span>for <gen-attr:min-time/> to <gen-attr:max-time/> minutes</span>
  <gen-attr:setting><span> on <gen:current/> heat</span></gen-attr:setting>
  <gen:literal>.</gen:literal>
 </my:layout>

 <xsl:variable name="vLayout" select="document('')/*/my:layout/*"/>
 <xsl:variable name="vDoc" select="/"/>

 <xsl:template match="node()|@*">
   <xsl:param name="pCurrent"/>
     <xsl:copy>
       <xsl:apply-templates select="node()|@*">
       <xsl:with-param name="pCurrent" select="$pCurrent"/>
       </xsl:apply-templates>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="/">
  <xsl:apply-templates select="$vLayout">
   <xsl:with-param name="pCurrent" select="$vDoc/*"/>
  </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="gen-attr:*">
  <xsl:param name="pCurrent"/>
  <xsl:value-of select="$pCurrent/@*[name() = local-name(current())]"/>
 </xsl:template>

 <xsl:template match="gen-attr:setting">
  <xsl:param name="pCurrent"/>
  <xsl:variable name="vnextCurrent" select=
   "$pCurrent/@*[name() = local-name(current())]"/>
  <xsl:apply-templates select="node()[$vnextCurrent]">
    <xsl:with-param name="pCurrent" select="$vnextCurrent"/>
  </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="gen:current">
  <xsl:param name="pCurrent"/>
   <xsl:value-of select="$pCurrent"/>
 </xsl:template>

 <xsl:template match="gen:literal">
  <xsl:apply-templates/>
 </xsl:template>
</xsl:stylesheet>

この変換により、必要な出力の視覚的(骨格)表現を作成し、それを使用してソースXMLドキュメントからの必要なデータを「入力」する方法がわかります。

結果は最初のソリューションの結果と同じです。この変換を「現状のまま」実行すると、多くの名前空間が生成されます。これらは無害であり、レイアウトが別のXMLファイルにある場合は生成されません。

于 2012-05-14T03:46:54.780 に答える