1

私は次のxmlを持っています:

<p>Lorem ipsum dolor sit amet, <b>consectetur adipisicing</b> elit, <i>sed do<sup>2</sup></i> eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>

また、最初の200文字のみを表示したいのですが、単語の途中で途切れない場合があり、書式設定要素を保持したいと思います。したがって、変換後の上記のフラグメントは次のようになります。

<p>Lorem ipsum dolor sit amet, <b>consectetur adipisicing</b> elit, <i>sed do<sup>2</sup></i> eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ...</p>

これが可能かどうか誰かが知っていますか?前もって感謝します!

4

1 に答える 1

2

このXSLT2.0変換

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xsl:output omit-xml-declaration="yes" indent="no"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="pmaxChars" as="xs:integer" select="200"/>

 <xsl:variable name="vPass1">
   <xsl:apply-templates select="/*"/>
 </xsl:variable>

 <xsl:template match="node()|@*" mode="#default pass2">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*" mode="#current"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="/">
  <xsl:apply-templates select="$vPass1" mode="pass2"/>
 </xsl:template>

 <xsl:template match=
 "text()[sum(preceding::text()/string-length()) ge $pmaxChars]"/>

 <xsl:template match="text()[not(following::text())]" mode="pass2">
   <xsl:variable name="vPrecedingLength"
     select="sum(preceding::text()/string-length())"/>

   <xsl:variable name="vRemaininingLength"
     select="$pmaxChars -$vPrecedingLength"/>

  <xsl:sequence select=
   "replace(.,
            concat('(^.{0,', $vRemaininingLength, '})\W.*'),
            '$1'
            )
   "/>
 </xsl:template>
</xsl:stylesheet>

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

<p>Lorem ipsum dolor sit amet, <b>consectetur adipisicing</b> elit, <i>sed do<sup>2</sup></i> eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>

必要な正しい結果を生成します(すべてのテキストノードの合計の長さが200を超えず、単語の境界で切り捨てが実行され、これが可能な最大の合計文字列長を残した切り捨てであるXMLドキュメント):

<p>Lorem ipsum dolor sit amet, <b>consectetur adipisicing</b> elit, <i>sed do<sup>2</sup></i> eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut</p>

説明

  1. これは、グローバル/外部パラメータとして最大数のテキスト文字を受け入れる一般的なソリューションです$pmaxChars

  2. これは2パスソリューションです。pass1では、IDルールは、すべてのテキストノードを削除するテンプレートによってオーバーライドされます。このテンプレートの開始文字には、許可される最大文字数よりも大きいインデックス(すべてのテキストノードの合計連結)があります。したがって、pass1の結果は、最大許容長の「ブレーク」が最後のテキストノードで発生するXMLドキュメントです。

  3. パス2では、最後のテキストノードに一致するテンプレートでIDルールをオーバーライドします。replace()次の関数を使用します。

...。

replace(.,
            concat('(^.{0,', $vRemaininingLength, '})\W.*'),
            '$1'
            )

これにより、文字列全体が一致し、角かっこの間の部分式に置き換えられます。この部分式は動的に構築され、文字列の先頭から始まり、0から$vRemaininingLength(最大許容長から先行するすべてのテキストノードの全長を引いたもの)の文字を含む最長の部分文字列と一致し、その直後に単語境界文字が続きます。

更新

トリミングのためにテキストノードの子孫がない(「空」である)結果の要素を取り除くには、次のテンプレートを追加するだけです。

 <xsl:template match=
 "*[(.//text())[1][sum(preceding::text()/string-length()) ge $pmaxChars]]"/>
于 2012-05-15T04:33:09.430 に答える