2

私はxslを初めて使用し、複数のxmlドキュメントでノードをカウントする際の問題に直面しました。これが私のXSLTフラグメントです:

<xsl:variable name="count">
    <xsl:for-each select="document(./log/@file)/testResults/*[not(@lb = preceding::*/@lb)]">
            <xsl:value-of select="count(../*[@lb = current()/@lb])"/>
    </xsl:for-each>
</xsl:variable>

ここで、。/ log /@fileはいくつかのxmlドキュメントを作成します。xmlドキュメントのサンプル:

<testResults version="1.2">
        <sample t="63" lt="0" ts="1343919489839" s="true" lb="jp@gc - Dummy Sampler" rc="200" rm="OK" tn="Thread Group 1-1" dt="text" by="114"/>
        <sample t="62" lt="0" ts="1343919489903" s="true" lb="jp@gc - Dummy Sampler" rc="200" rm="OK" tn="Thread Group 1-1" dt="text" by="114"/>
        <sample t="58" lt="0" ts="1343919490063" s="true" lb="jp@gc - Dummy Sampler" rc="200" rm="OK" tn="Thread Group 1-1" dt="text" by="114"/>
        <sample t="13" lt="0" ts="1343919490210" s="true" lb="jp@gc - Dummy Sampler" rc="200" rm="OK" tn="Thread Group 1-1" dt="text" by="114"/>
        <sample t="37" lt="0" ts="1343919490223" s="true" lb="jp@gc - Dummy Sampler" rc="200" rm="OK" tn="Thread Group 1-1" dt="text" by="114"/>
</testResults>

解析されたすべてのドキュメントで同じ構造になっています。

そして最後に問題...count関数は1つのドキュメントのcountを正しく返します。ただし、次のカウント結果は前の結果と連結されます。私の目標は、各反復の結果を合計することです。

したがって、最初の反復で15のマッチがあり、2番目の反復で4つの一致がある場合、カウント変数は154に設定されます。

これを手伝ってもらえますか?

PS私はlb属性でグループ化されたtestResultsの子要素を数えています

Ppsxslバージョンは1.0です

ありがとう、ヴァレリー

4

1 に答える 1

1

パイプラインのデザインで行きます。最初の段階では、特定のドキュメントについて、次のようなものを使用して、すべての@lbカウントを収集します...

<xsl:variable name="phase-1-output">
  <xsl:apply-templates select="..some-expression.../@file" mode="phase-1">
</xsl:variable>

<template match="@file" mode="phase-1">
 <xsl:apply-templates select="document(.)/testResults/sample" mode="phase-1" />
</template>

<xsl:template match="*" mode="phase-1" />

<xsl:template match="testResults/*[not(@lb = preceding::*/@lb)]" mode="phase-1" >
 <lb-group key="{@lb}">
  <xsl:number count="../*[@lb = current()/@lb]" />
 <lb-group>
</xsl:variable>

これにより、カウントとキーを含む要素のリスト(lb-group)を含む変数($ phase-1-output)が得られます。最初のテンプレートのselect式を、問題のあるスペースに必要なものに置き換えます。

ドキュメント間で共有される@lb値がある場合がありますが、これらをグループ化して合計する必要があると思います。したがって、フェーズ2では、入力が$ phase-1-output変数からのものであり、カウントではなく合計することを除いて、フェーズ1で行ったのと同じグループ化およびカウント手法を適用します。$ phase-1-output内のlb-groupsにアクセスするには、node-set()関数を使用する必要があります。

これで十分か、完全なスタイルシートが必要かどうかをお知らせください。


アップデート

OPは完全なスタイルシートを要求したので、ここにあります。提供された適切なサンプルデータが不足しているため、OPが提供したものと同じ顕著な機能を備えたサンプル入力ドキュメントをいくつか作成しましたが、Q&Aサイトに適したように削減および簡略化されました。

入力

2つの入力ファイルがあるとします。URLがin1.xmlの最初のファイルには、次の内容が含まれています。

<testResults category="citrus">
 <sample lb="lemon" />
 <sample lb="lemon" />
 <sample lb="green apple" />
 <sample lb="green apple" />
 <sample lb="green apple" />
</testResults>

また、URLがin2.xmlの別のファイルには、次の内容が含まれています。

<testResults category="green food">
 <sample lb="green apple" />
 <sample lb="celery soup" />
 <sample lb="peas" />
 <sample lb="peas" />
</testResults>

OPの規定された要件は...

lb属性でグループ化されたtestResultsの子要素をカウントします

必要な出力

したがって、必要な出力は次のようになります。OPがそれを供給するのを忘れたので、私は非情報構造を発明しました。

<root>
   <lb-group lb-key="lemon">2</lb-group>
   <lb-group lb-key="green apple">4</lb-group>
   <lb-group lb-key="celery soup">1</lb-group>
   <lb-group lb-key="peas">2</lb-group>
</root>

読者は4つの青リンゴがあることに気付くでしょう。3つは最初の入力ドキュメントからのもので、1つは2番目の入力ドキュメントからのものです。OPはファイルの境界を越えてカウントしたいと思っていました。分離が必要な場合、つまり、厳密にファイルごとに数える場合は、お知らせください。

ソリューション

Saxon XSLTプロセッサでは、下位互換モードで、この結果は、前述のパイプライン設計を実装する次のXSLT1.0スタイルシートによって実現できます。

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:so="http://stackoverflow.com/questions/11847434"
  xmlns:exslt="http://exslt.org/common"
  exclude-result-prefixes="xsl so exslt">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
<xsl:strip-space elements="*" />

<xsl:variable name="test-result-files">
 <so:file file="in1.xml" />
 <so:file file="in2.xml" />
</xsl:variable>

<xsl:template match="/" >
 <root>
  <xsl:variable name="phase-1-output" >
    <xsl:apply-templates select="document('')/*/xsl:variable
      [@name='test-result-files']/so:file/@file" mode="phase-1" />
  </xsl:variable>
  <xsl:apply-templates select="$phase-1-output/lb-group" mode="phase-2" />
 </root>
</xsl:template>

<xsl:template match="@file" mode="phase-1">
 <xsl:apply-templates select="document(.)/testResults/sample" mode="phase-1" />
</xsl:template>

<xsl:template match="*" mode="phase-1" />

<xsl:template match="testResults/*[not(@lb = following::*/@lb)]" mode="phase-1" >
 <xsl:variable name="lb-key" select="@lb" />
 <lb-group lb-key="{$lb-key}">
  <xsl:number count="*[@lb = $lb-key]" />
 </lb-group>
</xsl:template>    

<xsl:template match="*" mode="phase-2" />

<xsl:template match="lb-group[not(@lb-key = following::*/@lb-key)]" mode="phase-2">
 <xsl:copy>
  <xsl:copy-of select="@*" />
  <xsl:value-of select="sum(../*[@lb-key=current()/@lb-key])" />
 </xsl:copy>
</xsl:template>

</xsl:stylesheet> 

警告

XSLTエンジンが何であるかによっては、ラインを交換する必要があるかもしれません...

  <xsl:apply-templates select="$phase-1-output/lb-group" mode="phase-2" />

...と...

  <xsl:apply-templates select="xslt:node-set($phase-1-output)/lb-group" mode="phase-2" />

...またはMSプロセッサを使用している場合は、Microsoftと同等のもの。

于 2012-08-08T05:06:37.033 に答える