2

Umbraco XSLT バージョン 1 について。

私は約持っています。XML の 150 のニュース項目。このように言いましょう (この xml/xslt に慣れるまでは、すべて疑似コードです):

<news>
  <data alias=date>2008-10-20</data>
</news>
<news>
  <data alias=date>2009-11-25</data>
</news><news>
  <data alias=date>2009-11-20</data>
</news> etc. etc....

XML を実行して、ニュース アーカイブとして html 出力を作成したいと思います。次のようなもの (タグは重要ではありません):

2008
  Jan
  Feb
  ...
2009
  Jan
  Feb
  Mar
  etc. etc.

ネストされた for-each (疑似コード) しか考えられません。

var year_counter = 2002
var month_counter = 1
<xsl:for-each select="./data [@alias = 'date']=year_counter">
  <xsl:for-each select="./data [@alias = 'date']=month_counter">
    <xsl:value-of select="data [@alias = 'date']>
  "...if month_counter==12 end, else month_counter++ ..."
  </xsl:for-each>
"... year_counter ++ ..."
</xsl:for-each>

しかし、あるプログラマーは、10 年をループすると 120 回のループが発生し、それは悪いコーディングであると指摘しています。Umbraco は結果をキャッシュしていると思うので、私はあまり気にしていません。150 レコードの。

多くのニュース項目をソートして出力し、それらを年ごとにグループ化し、毎年月ごとにグループ化する方法の手がかりはありますか?

Br. アンダース

4

4 に答える 4

4

次のソリューションでは、このXMLファイルを使用しました。

<root>
  <news>
    <data alias="date">2008-10-20</data>
  </news>
  <news>
    <data alias="date">2009-11-25</data>
  </news>
  <news>
    <data alias="date">2009-11-20</data>
  </news>
  <news>
    <data alias="date">2009-03-20</data>
  </news>
  <news>
    <data alias="date">2008-01-20</data>
  </news>
</root>

そしてこのXSLT1.0変換:

<xsl:stylesheet 
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:cfg="http://tempuri.org/config"
  exclude-result-prefixes="cfg"
>
  <xsl:output method="xml" encoding="utf-8" />

  <!-- index news by their "yyyy" value (first 4 chars) -->
  <xsl:key 
    name="kNewsByY"  
    match="news" 
    use="substring(data[@alias='date'], 1, 4)" 
  />
  <!-- index news by their "yyyy-mm" value (first 7 chars) -->
  <xsl:key 
    name="kNewsByYM" 
    match="news" 
    use="substring(data[@alias='date'], 1, 7)" 
  />

  <!-- translation table (month number to name) -->
  <config xmlns="http://tempuri.org/config">
    <months>
      <month id="01" name="Jan" />
      <month id="02" name="Feb" />
      <month id="03" name="Mar" />
      <month id="04" name="Apr" />
      <month id="05" name="May" />
      <month id="06" name="Jun" />
      <month id="07" name="Jul" />
      <month id="08" name="Aug" />
      <month id="09" name="Sep" />
      <month id="10" name="Oct" />
      <month id="11" name="Nov" />
      <month id="12" name="Dec" />
    </months>
  </config>

  <xsl:template match="root">
    <xsl:copy>
      <!-- group news by "yyyy" -->
      <xsl:apply-templates mode="year" select="
        news[
          generate-id()
          =
          generate-id(key('kNewsByY', substring(data[@alias='date'], 1, 4))[1])
        ]
      ">
        <xsl:sort select="data[@alias='date']" order="descending" />
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>

  <!-- year groups will be enclosed in a <year> element -->
  <xsl:template match="news" mode="year">
    <xsl:variable name="y" select="substring(data[@alias='date'], 1, 4)" />
    <year num="{$y}">
      <!-- group this year's news by "yyyy-mm" -->
      <xsl:apply-templates mode="month" select="
        key('kNewsByY', $y)[
          generate-id() 
          =
          generate-id(key('kNewsByYM', substring(data[@alias='date'], 1, 7))[1])
        ]
      ">
        <xsl:sort select="data[@alias='date']" order="descending" />
      </xsl:apply-templates>
    </year>
  </xsl:template>

  <!-- month groups will be enclosed in a <month> element -->
  <xsl:template match="news" mode="month">
    <xsl:variable name="ym" select="substring(data[@alias='date'], 1, 7)" />
    <xsl:variable name="m" select="substring-after($ym, '-')" />
    <!-- select the label of the current month from the config -->
    <xsl:variable name="label" select="document('')/*/cfg:config/cfg:months/cfg:month[@id = $m]/@name" />
    <month num="{$m}" label="{$label}">
      <!-- process news of the current "yyyy-mm" group -->
      <xsl:apply-templates select="key('kNewsByYM', $ym)">
        <xsl:sort select="data[@alias='date']" order="descending" />
      </xsl:apply-templates>
    </month>
  </xsl:template>

  <!-- for the sake of this example, news elements will just be copied -->
  <xsl:template match="news">
    <xsl:copy-of select="." />
  </xsl:template>
</xsl:stylesheet>

変換が適用されると、次の出力が生成されます。

<root>
  <year num="2009">
    <month num="11" label="Nov">
      <news>
        <data alias="date">2009-11-25</data>
      </news>
      <news>
        <data alias="date">2009-11-20</data>
      </news>
    </month>
    <month num="03" label="Mar">
      <news>
        <data alias="date">2009-03-20</data>
      </news>
    </month>
  </year>
  <year num="2008">
    <month num="10" label="Oct">
      <news>
        <data alias="date">2008-10-20</data>
      </news>
    </month>
    <month num="01" label="Jan">
      <news>
        <data alias="date">2008-01-20</data>
      </news>
    </month>
  </year>
</root>

それはすでに正しい構造を持っています、あなたはあなた自身のニーズに実際の外観を適応させることができます。

解決策は、2段階のミュンヒアングループ化アプローチです。第1フェーズでは、ニュースアイテムは年ごとにグループ化され、第2フェーズでは年月ごとにグループ化されます。

ここでの私の説明を参照して<xsl:key>ください。同様の問題ですが、他の質問を読む必要はありません。私の答えの下部を読んでください。key()

于 2009-11-20T14:57:15.967 に答える
2

必要なのは、いわゆるMuenchian Groupingメソッドです。これは、XSLT のこの問題/パターンに正確に対処します。

基本的に、一意のキーを見つけて、使用されているキーに含まれるエントリをループすることでグループ化します。

于 2009-11-20T13:27:39.123 に答える
0

ルセロに加えて、月の名前が削除される問題を回避するために、Xslグループ化の重複の問題を確認してください

于 2009-11-20T13:34:24.573 に答える
0

XSLTでmonth_counter++を実行することはできません。これは手続き型言語ではなく、XSLTの動作方法でもありません。したがって、これがこのように機能しない場合、これが非効率的であることを心配するのは無意味です。

これは、XSLTの首の大きな痛みのように見えます。私のXSLTは、実際に実装しようとするほど新鮮ではありません。しかし、ここに2つの方法があります。

1)

  • xsl:keyを使用してすべての一意の年を抽出します-
  • その後、これらの年を繰り返します。毎年行う
  • xsl:keyを使用してすべての月を抽出します
  • 毎月行う

2)(うまくいけば簡単そうです。)

  • それらを日付で並べ替え、並べ替えられた配列を変数に保存します
  • この変数を繰り返します(変数がソートされた配列を保持することが重要です)
  • 毎回前の兄弟を見てください。年/月が現在の要素と等しくない場合は、適切なヘッダーを記述します

3)XSLTを忘れて、実際のプログラミング言語を使用します。

于 2009-11-20T13:36:01.357 に答える