2

XSLTでテキストを出力しています。各セクションの行数を数えて、出力ファイルに書き出す必要があります。これはどのように行うことができますか?

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

HDR+aaa:bbb'
AAA+78901234567890+文字列1:文字列2'
BBB+123+文字列'
CCC+321:1212'
DDD+112211'
DDD+121122'
XXX+number_of_records+78901234567890'
AAA+1234567890+文字列1:文字列2'
BBB+123+文字列'
CCC+321:1212'
DDD+1212:2121'
BBB+123+文字列'
BBB+122+文字列'
CCC+文字列'
XXX+number_of_records+1234567890'

number_of_records には、AAA から XXX までの行数 (両方の行を含む) が含まれている必要があります。最初のセクションの行数は 6、2 番目のメッセージの行数は 8 にする必要があります。各セクションの最初と最後の行は、同じ一意の ID 番号を共有します。

XSLT 内の処理が非常に多いため、ソースから行数を数えることはできません。

4

3 に答える 3

2

これを行う概念的に簡単な方法は、第 2 段階のプロセスを使用することです。最初の変換の出力 (投稿したもの) を取得し、テンプレート (または @Alejandro のようなスタイルシート) を実行して行に解析し、AAA... で始まりXXX. 、、およびを使用してこれを行うための非常に明確で実用的なチュートリアルについては、XSLT 2.0 を使用したアップコンバージョンを参照してください。次に、グループごとに行数を数え、各行を再出力し、行数を XXX レコードに挿入します。tokenize()xsl:analyze-stringxsl:for-each-group

しかし、最初の出力を解析することになるため、これは非効率的であり、エラーが発生しやすくなります。スタイルシートが既に内部的に持っていた情報のシリアル化を解析するのはなぜですか? 最初の出力を XML に変更することで、非効率性を回避できます。

<hdr>
  <section id="78901234567890">
    <!-- It sounds like AAA's ID actually applies to the section? -->
    <AAA String1="..." String2="..."/>
    <BBB .../>
    <!-- no need to include XXX at this stage AFAICT -->
  </section>
  <section id="1234567890">
    ...
  </section>
</hdr>

次に、第 2 段階のテンプレート (または別のスタイルシート) がこの XML を入力として受け取り、上記で行ったように非常に簡単にシリアル化して、行をカウントします。XSLT 1.0 では、別のスタイルシートを使用して出力 XML を処理するか、拡張関数 node-set()を使用する必要があります。(ただし、別のスタイルシート プロセッサを使用しても、SAX を使用して 2 つのスタイルシート プロセッサを一緒にパイプライン処理できれば、中間 XML を再解析するコストを回避できます。) XSLT 2.0 では、1 つのテンプレートの XML 出力を次のように処理できます。別のテンプレート、制限なし。

于 2010-08-23T16:00:14.947 に答える
1

入力サンプルとスタイルシートを投稿してそのテキスト出力を構築するまで、このスタイルシートは次のようになります。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:template match="result" name="result">
        <xsl:param name="pString" select="."/>
        <xsl:variable name="vAfter" select="substring-after($pString, 'AAA+')"/>
        <xsl:choose>
            <xsl:when test="$vAfter!=''">
                <xsl:variable name="vId" 
                        select="substring-before($vAfter, '+')"/>
                <xsl:variable name="vEnd" 
                  select='concat("XXX+number_of_records+",$vId,"&apos;&#xA;")'/>
                <xsl:variable name="vInto" 
                        select="substring-before($vAfter,$vEnd)"/>
                <xsl:value-of 
                        select='concat(substring-before($pString,"AAA+"),
                             "AAA+",
                             $vInto,
                             "XXX+",
                             string-length(translate($vInto,
                                                     translate($vInto,
                                                               "&#xA;",
                                                               ""),
                                                     "")) + 1,
                             "+",$vId,"&apos;&#xA;")'/>
                <xsl:call-template name="result">
                    <xsl:with-param name="pString" 
                        select="substring-after($vAfter,$vEnd)"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$pString"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

この入力で:

<result>
HDR+aaa:bbb'
AAA+78901234567890+String1:String2'
BBB+123+String'
CCC+321:1212'
DDD+112211'
DDD+121122'
XXX+number_of_records+78901234567890'
AAA+1234567890+String1:String2'
BBB+123+String'
CCC+321:1212'
DDD+1212:2121'
BBB+123+String'
BBB+122+String'
CCC+String'
XXX+number_of_records+1234567890'
</result>

出力:

HDR+aaa:bbb'
AAA+78901234567890+String1:String2'
BBB+123+String'
CCC+321:1212'
DDD+112211'
DDD+121122'
XXX+6+78901234567890'
AAA+1234567890+String1:String2'
BBB+123+String'
CCC+321:1212'
DDD+1212:2121'
BBB+123+String'
BBB+122+String'
CCC+String'
XXX+8+1234567890'
于 2010-08-23T15:06:47.620 に答える
0

私の解決策: number_of_records を呼び出すたびに 1 ずつインクリメントする拡張関数を作成しました。xsl:comment を使用して、実際に数値を出力する必要があるまで出力を抑制します。XXX+ 行ごとに number_of_records をリセットしました。

これを 2 つの手順で行うと、面倒なことが多すぎます。

于 2010-08-26T14:25:25.680 に答える