3

次のような XML ファイルがあります...

    <states>
 <state>
  <name>North Carolina</name>
  <city>Charlotte</city>
 </state>
 <state>
  <name>Alaska</name>
  <city>Fairbanks</city>
 </state>
 <state>
  <name>Virginia</name>
  <city>Leesburg</city>
 </state>
 <state>
  <name>Alaska</name>
  <city>Coldfoot</city>
 </state>
 <state>
  <name>North Carolina</name>
  <city>Harrisburg</city>
 </state>
 <state>
  <name>Virginia</name>
  <city>Ashburn</city>
 </state>  
</states>

各州をリストしたレポートを作成する必要があり、アルファベット順で各都市が続きます....など..

Alaska - Fairbanks, Coldfoot
North Carolina - Charlotte, Harrisburg
Virginia - Leesburg, Ashburn

(都市はアルファベット順である必要はなく、州だけです)

状態/状態で for-each を実行し、名前で並べ替えて処理することで、これを解決しようとしました。このような....

    <xsl:for-each select="states/state">
       <xsl:sort select="name" data-type="text" order="ascending"/>
       <xsl:value-of select="name"/>-<xsl:value-of select="city"/>
    </xsl:for-each>   

これは私に与えた....

 Alaska - Fairbanks
 Alaska - Coldfoot
 North Carolina - Charlotte
 North Carolina - Harrisburg
 Virginia - Leesburg
 Virginia - Ashburn

並べ替えが機能したので、グループ化したいと思います。私が考えることができた唯一のことは、以前の状態と比較することでした.ソートされているので、状態値が変更されていないかどうかを認識する必要があります. このような...

<xsl:for-each select="states/state">
             <xsl:sort select="name" data-type="text" order="ascending"/>
  <xsl:variable name="name"><xsl:value-of select="name">
  <xsl:variable name="previous-name"><xsl:value-of select="(preceding-sibling::state)/name">
  <xsl:if test="$name != $previous-name">
   <br/><xsl:value-of select="name"/>-
  </xsl:if>
  <xsl:value-of select="city"/>
 </xsl:for-each>

悲しいことに、前の兄弟機能はこの種ではうまく機能しないようです。そのため、初めて (最初のアラスカで) 最初のノースカロライナが前の兄弟として表示されました。これは、私の好みではなかったいくつかの奇妙な結果を引き起こします。

それで、私は XSLT1.0 を使用しています...何か考え/提案はありますか?

ありがとう

4

3 に答える 3

5

このスタイルシート:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="kStateByName" match="state" use="name"/>
    <xsl:output method="text"/>
    <xsl:template match="/">
        <xsl:apply-templates
                   select="/*/state[count(.|key('kStateByName',name)[1])=1]">
            <xsl:sort select="name"/>
        </xsl:apply-templates>
    </xsl:template>
    <xsl:template match="state">
        <xsl:value-of select="concat(name,' - ')"/>
        <xsl:apply-templates select="key('kStateByName',name)/city"/>
    </xsl:template>
    <xsl:template match="city">
        <xsl:value-of select="concat(.,substring(', ', 
                                                 1 div (position()!=last())),
                                       substring('&#xA;',
                                                 1 div (position()=last())))"/>
    </xsl:template>
</xsl:stylesheet>

出力:

Alaska - Fairbanks, Coldfoot
North Carolina - Charlotte, Harrisburg
Virginia - Leesburg, Ashburn

: 州名でグループ化。区切り部分文字列式はプル スタイル (都市にテンプレートを適用) でのみ機能します

XSLT 2.0 ソリューション:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:template match="states">
        <xsl:for-each-group select="state" group-by="name">
            <xsl:sort select="name"/>
            <xsl:value-of select="concat(name,
                                         ' - ',
                                         string-join(current-group()/city,', '),
                                         '&#xA;')"/>
        </xsl:for-each-group>
    </xsl:template>
</xsl:stylesheet>

冗談として、この XPath 2.0 式は次のようになります。

string-join(for $state in distinct-values(/*/*/name)
            return concat($state,
                          ' - ',
                          string-join(/*/*[name=$state]/city,
                                      ', ')),
            '&#xA;')
于 2010-09-23T20:52:35.980 に答える
1

XSLT 1.0 でグループ化するには、おそらくMuenchian Methodを使用する必要があります。理解するのは難しいかもしれませんが、それが機能するようになったら、準備ができているはずです.

于 2010-09-23T20:23:46.107 に答える
0

これにより、個別の状態のリストが返されます。

  <xsl:for-each select="states/state">
     <xsl:sort select="name" />
     <xsl:if test="not(name = preceding-sibling::state/name)" >
         <xsl:value-of select="name" />
     </xsl:if>
  </xsl:for-each>

あなたのサンプル XML を使用し、上記で小さなスタイル シートを作成し、Xalan-j で実行すると、次のように返されます。

アラスカ ノースカロライナ バージニア

したがって、そこから、テンプレートまたは別の for-each ループを適用して、個別の州ごとに都市のリストを取得できるはずです。

クリス

于 2010-09-23T22:10:41.703 に答える