3

私の XSLT 変換には、1 つのノードを処理するために使用する必要がある 2 つの分析文字列があります。それらは 1 つずつ正常に動作しますが、それらを組み合わせる方法がわかりません。

XML ドキュメントは次のようになります。

<article>
    <title>Article 1</title>
    <text><![CDATA[Lorem ipsum dolor sit amet, s consectetur adipiscing elit. Donec lorem diam, eleifend sed mollis id, condimentum in velit.

Sed sit amet erat ac mauris adipiscing elementum. Pellentesque eget quam augue, id faucibus magna.

Ut malesuada arcu eu elit sodales sodales. Morbi tristique porttitor tristique. Praesent eget vulputate dui. Cras ut tortor massa, at faucibus ligula.]]></text>
</article>

ここに私のXSLTがあります:

<xsl:template match="/">
    <html>
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
            <title>Page title</title>
        </head>
        <body>
            <xsl:for-each select="article">
                <h1><xsl:value-of select="./title"/></h1>

                <!-- This adds paragraphs tags instead of empty lines in the text -->
                <xsl:analyze-string select="./text" regex="&#xa;">
                    <xsl:non-matching-substring>
                        <p>
                            <xsl:value-of select="." disable-output-escaping="yes"/>
                        </p>
                    </xsl:non-matching-substring>
                </xsl:analyze-string> 

                <!-- This is Czech language specific. It looks for ' s ' (or other letter) and changes second space for &nbsp;. So after that it is ' s&nbsp;'. -->
                <xsl:analyze-string select="./text" regex="(\s[k/K/s/S/v/V/z/Z]\s)">
                    <xsl:matching-substring>
                        <xsl:text> </xsl:text>
                        <xsl:value-of select="replace(., ' ','')" disable-output-escaping="yes"/>
                        <xsl:text disable-output-escaping="yes"><![CDATA[&nbsp;]]></xsl:text>
                    </xsl:matching-substring>
                    <xsl:non-matching-substring>
                        <xsl:value-of select="." disable-output-escaping="yes"/>
                    </xsl:non-matching-substring>
                </xsl:analyze-string>
            </xsl:for-each>
        </body>
    </html>
</xsl:template>

生成されたテキストに両方の分析文字列を適用する必要があるため<p>、段落のタグがあり&nbsp;、適切な場所にも追加されます。

私の望ましい出力は次のようになります。

<h1>Article 1</h1>    
<p>Lorem ipsum dolor sit amet, s&nbsp;consectetur adipiscing elit. Donec lorem diam, eleifend sed mollis id, condimentum in velit.</p>
<p>Sed sit amet erat ac mauris adipiscing elementum. Pellentesque eget quam augue, id faucibus magna.</p>
<p>Ut malesuada arcu eu elit sodales sodales. Morbi tristique porttitor tristique. Praesent eget vulputate dui. Cras ut tortor massa, at faucibus ligula.</p>

これを行う方法はありますか?時間を割いて私を助けてくれてありがとう。

4

3 に答える 3

3

Dimitreのソリューションに対する私の微調整は次のとおりです。

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

 <xsl:template match="/*/text">
   <xsl:for-each select="tokenize( replace(., '\s([kKsSvVzZ])\s', ' $1&#xA0;'), '\n')">
     <p><xsl:value-of select="."/></p>
  </xsl:for-each>
 </xsl:template>

 <xsl:template match="title">
  <h1><xsl:value-of select="."/></h1>
 </xsl:template>
</xsl:stylesheet>

ノート

  1. 「文字 s/S/v/V/k/K/z/Z」の意味がわかりません。これは有効な正規表現ではありません。明確にする必要があります。私はあなたが文字クラス [sSvVkKzZ] を意味していると推測しました
  2. 明確ではありませんが、チェコ語への言及は、UTF-8 が ASCII よりも出力エンコーディングに適している可能性があることを示唆しています。
  3. 明確ではありませんが、予想される出力タグは、より適切なシリアル化が html であることを示唆しています。
  4. HTML シリアライゼーションを選択することの副次的な利点として、文字マップが不要になり、ソリューションがよりシンプルになります。組み込みの文字マップを HTML シリアライゼーションに活用できます。
  5. fn:tokenise() を使用すると、xsl:analyze-string/xsl:non-matching-substring ノードが不要になり、より厳密なソリューションが得られることはほぼ間違いありません。
  6. このソリューションは、Saxon でテストされました。
  7. バリエーションが可能です。たとえば、replace() 呼び出しを xsl:value-of 内に移動すると、より読みやすいと見なすことができます。
  8. 私のソリューションの欠点は、 disable-output-escaping="yes" では機能しないことです。ただし、これが必要だと思われる場合は、その理由をもう一度しっかりと確認することをお勧めします。HTML は、CDATA セクション内にない限り、HTML セーフ エンコーディングが必要です。disable-output-escaping をオンにして HTML を生成するという考えには、何か問題があります。おそらく私は質問を完全には理解していません。ポイントを明確にするユースケースを教えてください。
于 2012-05-21T06:45:13.603 に答える
3

この変換:

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

 <xsl:template match="/*/text">
  <xsl:analyze-string select=
   "replace(., '\ss\s', ' s&#xA0;')"
   regex="&#xA;">
    <xsl:non-matching-substring>
     <p><xsl:sequence select="."/></p>
    </xsl:non-matching-substring>
  </xsl:analyze-string>
 </xsl:template>

 <xsl:template match="title">
  <h1><xsl:value-of select="."/></h1>
 </xsl:template>
</xsl:stylesheet>

提供された XML ドキュメントに適用した場合:

<article>
  <title>Article 1</title>
<text><![CDATA[Lorem ipsum dolor sit amet, s consectetur adipiscing elit. Donec lorem diam, eleifend sed mollis id, condimentum in velit.
Sed sit amet erat ac mauris adipiscing elementum. Pellentesque eget quam augue, id faucibus magna.
Ut malesuada arcu eu elit sodales sodales. Morbi tristique porttitor tristique. Praesent eget vulputate dui. Cras ut tortor massa, at faucibus ligula.]]></text>
</article>

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

  <h1>Article 1</h1>
<p>Lorem ipsum dolor sit amet, s&#160;consectetur adipiscing elit. Donec lorem diam, eleifend sed mollis id, condimentum in velit.</p>
<p>Sed sit amet erat ac mauris adipiscing elementum. Pellentesque eget quam augue, id faucibus magna.</p>
<p>Ut malesuada arcu eu elit sodales sodales. Morbi tristique porttitor tristique. Praesent eget vulputate dui. Cras ut tortor massa, at faucibus ligula.</p>

: DOE は XSLT 2.0 の必須機能ではなく、XSLT 2.0 プロセッサが DOE をサポートするという保証がないため、DOE の使用はお勧めできません。代わりに使用する機能は、character mapsです。

次に、全体の変換は次のようになります。

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"
  encoding="ascii" use-character-maps="nbsp"/>

 <xsl:character-map name="nbsp">
  <xsl:output-character
  character="&#xA0;" string="&amp;nbsp;"/>
 </xsl:character-map>

 <xsl:template match="/*/text">
  <xsl:analyze-string select=
   "replace(., '\ss\s', ' s&#xA0;')"
   regex="&#xA;">
    <xsl:non-matching-substring>
     <p><xsl:sequence select="."/></p>
    </xsl:non-matching-substring>
  </xsl:analyze-string>
 </xsl:template>

 <xsl:template match="title">
  <h1><xsl:value-of select="."/></h1>
 </xsl:template>
</xsl:stylesheet>

同じ XML ドキュメント (上記) に適用すると、必要な正しい結果が生成されます。

  <h1>Article 1</h1>
<p>Lorem ipsum dolor sit amet, s&nbsp;consectetur adipiscing elit. Donec lorem diam, eleifend sed mollis id, condimentum in velit.</p>
<p>Sed sit amet erat ac mauris adipiscing elementum. Pellentesque eget quam augue, id faucibus magna.</p>
<p>Ut malesuada arcu eu elit sodales sodales. Morbi tristique porttitor tristique. Praesent eget vulputate dui. Cras ut tortor massa, at faucibus ligula.</p>
于 2012-05-20T22:42:26.247 に答える
2

あなたはそれをあまり明確にしていませんでしたが、質問の私の解釈は、2番目の xsl:analyze-string を使用して最初の出力を処理したかったということでした。最初の結果を変数に入れることでそれを行うことができますが、私の推奨は、各 xsl:analyze-string 呼び出しを関数の本体に入れ、関数合成を使用してそれらを合成することです。

<xsl:function name="f:one" as="xs:string">
  <xsl:param name="in" as="xs:string">
  <xsl:analyze-string select="in".../>
</xsl:function>

<xsl:function name="f:two" as="xs:string">
  <xsl:param name="in" as="xs:string">
  <xsl:analyze-string select="in".../>
</xsl:function>

... select="f:two(f:one(.))"...

ただし、あなたの場合、最初の xsl:analyze-string は replace() の単純な呼び出しを使用して実行できるため、より簡単です。

于 2012-05-21T08:07:25.893 に答える