2

XSLT の学習を始めたばかりで、重複した要素を無視するのに苦労しています。

私はスタック オーバーフローを検索しており、人々が同様の質問をしているのを見てきました。ファイルのどこで問題が発生したかを確認するために小さな例を試してみたところ、重複した要素を無視することができました。ただし、要素のタイプが複数ある場合、問題が発生するようです。

例えば:

File1.xml

<?xml-stylesheet type="text/xsl" href="merge2.xsl"?>

<Main>
    <Records>
        <Record>
            <Description>A</Description>
        </Record>
        <Record>
            <Description>A</Description>
        </Record>
        <Record>
            <Description>B</Description>
        </Record>
        <Record>
            <Description>C</Description>
        </Record>
    </Records>
</Main>

merge2.xsl

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/Transform">
<xsl:output method="html"/>
<xsl:template match="/">
    <table border="1">
        <tr>
            <th>Type</th>
            <th>Count</th>
        </tr>
        <xsl:for-each select="Main/Records/Record">
            <xsl:if test ="not(preceding-sibling::Record(Description/text() = current()/Description/text()])">
                <tr>
                    <td><xsl:value-of select="Description"/></td>
                    <td><xsl:value-of select="count(//Record[Description/text()=current()/Description/text()])"/></td>
                </tr>
            </xsl:if>
        </xsl:for-each>
    </table>
</xsl:template>
</xsl:stylesheet>

これはうまく機能し、望ましい結果が得られます。

Type    Count
 A        2
 B        1
 C        1

ただし、別の Records 要素を追加すると、2 つを次々に処理するように見えます。

<?xml-stylesheet type="text/xsl" href="merge2.xsl"?>

<Main>
    <Records>
        <Record>
            <Description>A</Description>
        </Record>
        <Record>
            <Description>A</Description>
        </Record>
        <Record>
            <Description>B</Description>
        </Record>
        <Record>
            <Description>C</Description>
        </Record>
    </Records>
    <Records>
        <Record>
            <Description>B</Description>
        </Record>
        <Record>
            <Description>A</Description>
        </Record>
        <Record>
            <Description>C</Description>
        </Record>
        <Record>
            <Description>C</Description>
        </Record>
    </Records>
</Main>

これにより、次のようになります。

Type        Count
 A            3
 B            2
 C            3
 B            2
 A            3
 C            3

レコードの最初のインスタンスを処理しているように見える場所で、次のインスタンスに移動します。2 つの重複を削除する方法はありますか?

Records の各インスタンスを通過するように for-each を変更しようとしましたが、別のテンプレートを作成しようとしましたが、うまく機能していないため、まだ何かが欠けているようです。

助けてくれてありがとう。

4

2 に答える 2

5

に置き換えpreceding-siblingてみてprecedingくださいxsl:if statement

tr遭遇したDescription値ごとに 1 回だけ発行するようにテストを作成するという正しい考えがありました。ただし、preceding-sibling親の直接の子のチェックバックは停止します。precedingはドキュメントの前の方でチェックを続けますRecords

Record(参考までに、あるべき場所にもタイプミスがありますRecord[。これらの変更を含む完全な運用上の変換を次に示します。

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html"/>
  <xsl:template match="/">
    <table border="1">
      <tr>
        <th>Type</th>
        <th>Count</th>
      </tr>
      <xsl:for-each select="Main/Records/Record">
        <xsl:if test ="not(preceding::Record[Description/text() = current()/Description/text()])">
          <tr>
            <td><xsl:value-of select="Description"/></td>
            <td><xsl:value-of select="count(//Record[Description/text()=current()/Description/text()])"/></td>
          </tr>
        </xsl:if>
      </xsl:for-each>
    </table>
  </xsl:template>
</xsl:stylesheet>
于 2013-09-19T15:36:58.280 に答える
1

@kjhughes はあなたの質問に答えることができましたが、より効率的なアプローチのためにMuenchain Methodを使用することをお勧めします。

これを行うには、グループ化するキーを定義します

<xsl:key name="Record-by-Description" match="Record" use="Description"/>

次に、そのキーを使用してそれらのアイテムをグループ化します

<xsl:apply-templates select="Record[generate-id() = generate-id(key('Record-by-Description', Description)[1])]" mode="group"/>

そして、そのキーを使用して、それらの特定のアイテムのみをカウントします

<xsl:value-of select="count(key('Record-by-Description', Description))"/>

このプロセスははるかに効率的で、毎回構造全体をナビゲートする必要はありません。

したがって、全体として、この XML を取得すると

<Main>
  <Records>
    <Record>
      <Description>A</Description>
    </Record>
    <Record>
      <Description>A</Description>
    </Record>
    <Record>
      <Description>B</Description>
    </Record>
    <Record>
      <Description>C</Description>
    </Record>
  </Records>
  <Records>
    <Record>
      <Description>B</Description>
    </Record>
    <Record>
      <Description>A</Description>
    </Record>
    <Record>
      <Description>C</Description>
    </Record>
    <Record>
      <Description>C</Description>
    </Record>
  </Records>
</Main>

そして、この XSLT をそれに適用します

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
  <xsl:output method="xml" indent="yes" />
  <xsl:key name="Record-by-Description" match="Record" use="Description"/>

  <xsl:template match="@* | node()">
    <xsl:apply-templates select="@* | node()"/>
  </xsl:template>

  <xsl:template match="Main">
    <table>
      <tr>
        <th>Type</th>
        <th>Count</th>
      </tr>
      <xsl:apply-templates select="Records"/>
    </table>
  </xsl:template>

  <xsl:template match="Records">
    <xsl:apply-templates select="Record[generate-id() = generate-id(key('Record-by-Description', Description)[1])]" mode="group"/>
  </xsl:template>

  <xsl:template match="Record" mode="group">
    <tr>
      <td>
        <xsl:value-of select="Description"/>
      </td>
      <td>
        <xsl:value-of select="count(key('Record-by-Description', Description))"/>
      </td>
    </tr>
  </xsl:template>

</xsl:stylesheet>

この出力を生成します

<table>
  <tr>
    <th>Type</th>
    <th>Count</th>
  </tr>
  <tr>
    <td>A</td>
    <td>3</td>
  </tr>
  <tr>
    <td>B</td>
    <td>2</td>
  </tr>
  <tr>
    <td>C</td>
    <td>3</td>
  </tr>
</table>
于 2013-09-19T16:13:51.253 に答える