2

ここでいくつかの例を試しましたが、それでも正しい出力を取得できません。私はこれまでXSLTをあまり使用していませんでした。「Detail」要素でグループ化し、そのグループに一致するすべての「Data」要素を「Detail」要素の子として取得したいと思います。

例:

入力

<?xml version="1.0" encoding="utf-8"?>
<File>
  <Detail type="A" group="1" >
    <Data>
      <Nr>1</Nr>
    </Data>
    <Data>
      <Nr>2</Nr>
    </Data>
  </Detail>
  <Detail type="B" group="1">
    <Data>
      <Nr>3</Nr>
    </Data>
    <Data>
      <Nr>4</Nr>
    </Data>
  </Detail>
  <Detail type="B" group="2">
    <Data>
      <Nr>5</Nr>
    </Data>
  </Detail>
  <Detail type="A" group="1">
    <Data>
      <Nr>6</Nr>
    </Data>
  </Detail>
</File>

必要な出力( "Detail type =" A "group =" 1 ">要素がグループ化され、そのグループに子として一致するすべての要素)

<?xml version="1.0" encoding="utf-8"?>
<File>
  <Detail type="A" group="1" >
    <Data>
      <Nr>1</Nr>
    </Data>
    <Data>
      <Nr>2</Nr>
    </Data>
    <Data>
      <Nr>6</Nr>
    </Data>
  </Detail>
  <Detail type="B" group="1">
    <Data>
      <Nr>3</Nr>
    </Data>
    <Data>
      <Nr>4</Nr>
    </Data>
  </Detail>
  <Detail type="B" group="2">
    <Data>
      <Nr>5</Nr>
    </Data>
  </Detail>
</File>

手伝ってくれてありがとう :)

4

2 に答える 2

3

I. XSLT 1.0

<xsl:for-each>これは、(通常はより再利用可能なアプローチです)ではなく、プッシュ指向のテンプレートを使用するソリューションです。

このXSLTの場合:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
  <xsl:output omit-xml-declaration="no" indent="yes" />
  <xsl:strip-space elements="*" />

  <xsl:key name="kDetailAttr" match="Detail" use="concat(@type, '+', @group)" />

  <xsl:template match="/*">
    <File>
      <xsl:apply-templates select="Detail[generate-id() = generate-id(key('kDetailAttr', concat(@type, '+', @group))[1])]" />
    </File>
  </xsl:template>

  <xsl:template match="Detail">
    <Detail type="{@type}" group="{@group}">
      <xsl:copy-of select="key('kDetailAttr', concat(@type, '+', @group))/Data" />
    </Detail>
  </xsl:template>

</xsl:stylesheet>

...元のXMLに適用されます:

<?xml version="1.0" encoding="UTF-8"?>
<File>
  <Detail type="A" group="1">
    <Data>
      <Nr>1</Nr>
    </Data>
    <Data>
      <Nr>2</Nr>
    </Data>
  </Detail>
  <Detail type="B" group="1">
    <Data>
      <Nr>3</Nr>
    </Data>
    <Data>
      <Nr>4</Nr>
    </Data>
  </Detail>
  <Detail type="B" group="2">
    <Data>
      <Nr>5</Nr>
    </Data>
  </Detail>
  <Detail type="A" group="1">
    <Data>
      <Nr>6</Nr>
    </Data>
  </Detail>
</File>

...必要な結果が生成されます:

<?xml version="1.0" encoding="utf-8"?>
<File>
  <Detail type="A" group="1">
    <Data>
      <Nr>1</Nr>
    </Data>
    <Data>
      <Nr>2</Nr>
    </Data>
    <Data>
      <Nr>6</Nr>
    </Data>
  </Detail>
  <Detail type="B" group="1">
    <Data>
      <Nr>3</Nr>
    </Data>
    <Data>
      <Nr>4</Nr>
    </Data>
  </Detail>
  <Detail type="B" group="2">
    <Data>
      <Nr>5</Nr>
    </Data>
  </Detail>
</File>

説明:

  • Muenchian Grouping Method(「インライン」グループ化メカニズムがないため、XSLT 1.0で必要です)を適切に適用することにより、一意のノードを見つけてその子孫をグループ化できます。

II。XSLT 2.0

このXSLTの場合:

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

  <xsl:template match="/*">
    <File>
      <xsl:for-each-group select="Detail"
      group-by="concat(@type, '+', @group)">
        <Detail type="{@type}" group="{@group}">
          <xsl:copy-of select="current-group()/Data" />
        </Detail>
      </xsl:for-each-group>
    </File>
  </xsl:template>
</xsl:stylesheet>

...元のXMLに適用されると、同じ正しい結果が生成されます。

説明:

  • XSLT 2.0のfor-each-group要素を適切に適用することで、同じ結果を得ることができます。
于 2012-09-11T23:32:02.153 に答える
1

注:この質問は、私が取り上げる前に6時間ビンで苦しんでいました。私の答えは、他の誰かがいくつかの本質的でないコメントを答えとして偽装する前に、2時間ビンで衰えました。


Muenchianのグループ化について調べます。これらのグループ化の問題に便利です。

ヘビーリフターは<xsl:key>、@ typeと@groupの連結に基づいてキーを作成し、この行は<xsl:for-each select="File/Detail[count(. | key('details', concat(@type,'_',@group))[1]) = 1]">、特定のキーを持つDetailノードの最初の出現を分離し、ひいては@groupと@の特定のペアを分離します。タイプ。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
     <xsl:key name="details" match="Detail" 
             use="concat(@type,'_',@group)"/>
    <xsl:template match='/'>
      <File>
        <xsl:for-each select="File/Detail[count(. | key('details', concat(@type,'_',@group))[1]) = 1]">
          <xsl:sort select="concat(@type,'_',@group)" />
          <Detail type="{@type}" group="{@group}">
            <xsl:for-each select="key('details', concat(@type,'_',@group))">
              <xsl:copy-of select="Data"/>  
           </xsl:for-each>
          </Detail>
       </xsl:for-each>
     </File>
   </xsl:template>   
</xsl:stylesheet>
于 2012-09-11T21:31:13.577 に答える