5
<ROOT>
<AA Aattr="xyz1">
    <BB bAttr1="firefox"  bAttr2="aaa" >
    </BB>   
    <BB bAttr1="chrome"   bAttr2="aaa" >
    </BB>
    <BB bAttr1="firefox"  bAttr2="bbb" >
    </BB>
    <BB bAttr1="chrome"   bAttr2="bbb" >
    </BB>
</AA>
<AA Aattr="xyz2">
    <BB bAttr1="firefox"  bAttr2="aaa" >
    </BB>   
    <BB bAttr1="chrome"   bAttr2="ccc" >
    </BB>
    <BB bAttr1="firefox"  bAttr2="ddd" >
    </BB>
</AA>

属性「Aattr」がxyz1であるノード「AA」から、ノード「BB」の属性「bAttr2」の個別の\一意の値を選択したい

与えられたxmlについて、「aaa」、「bbb」として出力する必要があると言います

キーを使用して次のロジックを試しました。しかし、うまくいきませんでした。助けてください

<xsl:key name="nameDistinct" match="BB" use="@bAttr1"/>
<xsl:template match="/">
<xsl:for-each select="ROOT/AA[@Aattr='xyz1']">
    <xsl:for-each select="BB[generate-id()=generate-id(key('nameDistinct',@bAttr2)[1])]">
    <xsl:value-of select="@bAttr2"/>            
    </xsl:for-each>
</xsl:for-each>
</xsl:template>
4

2 に答える 2

5

ここには2つのオプションがあります。

キーを定義するときに、キーで使用可能なアイテムをフィルタリングします。

  <xsl:key name="nameDistinct" match="AA[@Aattr = 'xyz1']/BB" use="@bAttr2"/>

  <xsl:template match="/">
    <xsl:for-each 
      select="ROOT/AA/BB[generate-id() =
                         generate-id(key('nameDistinct', @bAttr2)[1])]">
      <xsl:value-of select="@bAttr2"/>
    </xsl:for-each>
  </xsl:template>

またはグループ化式内でフィルタリングします。

  <xsl:key name="nameDistinct" match="BB" use="@bAttr2"/>

  <xsl:template match="/">
    <xsl:for-each 
      select="ROOT/AA/BB[generate-id() =
                         generate-id(key('nameDistinct', @bAttr2)
                                       [../@Aattr = 'xyz1']
                                       [1])]">
      <xsl:value-of select="@bAttr2"/>
    </xsl:for-each>
  </xsl:template>

前者のアプローチは少し面倒でなく、わずかに効率的ですが、後者ではグループ化(つまり、「xyz1」としてハードコードされていない値のグループ化)をパラメーター化できます。例:

  <xsl:key name="nameDistinct" match="BB" use="@bAttr2"/>

  <xsl:template match="/">
    <xsl:for-each select="ROOT/AA">
      <xsl:for-each
        select="BB[generate-id() =
                   generate-id(key('nameDistinct', @bAttr2)
                                    [../@Aattr = current()/@Aattr]
                                    [1])]">
        <xsl:value-of select="@bAttr2"/>
      </xsl:for-each>
    </xsl:for-each>
  </xsl:template>
于 2013-03-21T13:36:39.173 に答える
2

この変換

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:key name="kCompoundAttribs" match="BB"
  use="concat(generate-id(..), '+', @bAttr2)"/>

 <xsl:template match="/">
  <xsl:copy-of select=
   "/*/*[1]/*
     [generate-id()
     =
      generate-id(key('kCompoundAttribs',
                      concat(generate-id(..),'+', @bAttr2)
                      )[1]
                  )
     ]"/>
 </xsl:template>
</xsl:stylesheet>

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

<ROOT>
    <AA Aattr="xyz1">
        <BB bAttr1="firefox"  bAttr2="aaa" ></BB>
        <BB bAttr1="chrome"   bAttr2="aaa" ></BB>
        <BB bAttr1="firefox"  bAttr2="bbb" ></BB>
        <BB bAttr1="chrome"   bAttr2="bbb" ></BB>
    </AA>
    <AA Aattr="xyz2">
        <BB bAttr1="firefox"  bAttr2="aaa" ></BB>
        <BB bAttr1="chrome"   bAttr2="ccc" ></BB>
        <BB bAttr1="firefox"  bAttr2="ddd" ></BB>
    </AA>
</ROOT>

2つのBB要素を生成し、そのbAttr2属性には目的の個別の値のセットがあります(属性の文字列値のみが必要な場合は、xsl:apply-templatesまたはxsl:for-eachその式に使用するだけです)。

<BB bAttr1="firefox" bAttr2="aaa"/>
<BB bAttr1="firefox" bAttr2="bbb"/>

注意してください

このソリューションは、「フィルタリング」よりも単純で理解しやすく、効率的です:)

于 2013-03-22T03:34:42.443 に答える