2009-06-03 109 views
5

我想在XML文件中分組兄弟數據。XSLT分組兄弟姐妹

考慮:

<?xml version="1.0" encoding="UTF-8"?> 
<data> 
    <competition> 
     <timeline>10:00</timeline> 
     <fixture>team a v team b</fixture> 
     <fixture>team c v team d</fixture> 
     <timeline>12:00</timeline> 
     <fixture>team e v team f</fixture> 
     <timeline>16:00</timeline> 
     <fixture>team g v team h</fixture> 
     <fixture>team i v team j</fixture> 
     <fixture>team k v team l</fixture> 
    </competition> 
</data> 

我試圖產生:我現在用的是下面的XSLT

<?xml version="1.0" encoding="UTF-8"?> 
<data> 
    <competition> 
     <timeline time="10:00"> 
      <fixture>team a v team b</fixture> 
      <fixture>team c v team d</fixture> 
     </timeline> 
     <timeline time="12:00"> 
      <fixture>team e v team f</fixture> 
     </timeline> 
     <timeline time="16:00"> 
      <fixture>team g v team h</fixture> 
      <fixture>team i v team j</fixture> 
      <fixture>team k v team l</fixture> 
     </timeline> 
    </competition> 
</data> 

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 

    <xsl:template match="competition" > 

     <xsl:apply-templates select="timeline" /> 

    </xsl:template> 

    <xsl:template match="timeline"> 
     <timeline> 
      <xsl:attribute name="time" > 
       <xsl:value-of select="." /> 
      </xsl:attribute> 

      <xsl:apply-templates select="following-sibling::*" mode="copy"/> 

     </timeline> 
    </xsl:template> 

    <xsl:template match="fixture" mode="copy"> 
     <fixture> 
      <xsl:value-of select="." /> 
     </fixture> 
    </xsl:template> 

    <xsl:template match="timeline" mode="copy"> 
     <xsl:apply-templates select="following-sibling::*" mode="null" /> 
    </xsl:template> 

    <xsl:template match="*" mode="null"> 
    </xsl:template> 
</xsl:stylesheet> 

我的問題是,它不停止加工夾具節點到達下一個時間線時

+0

不僅如此,你的XSLT不會相同組的時間表,如果他們不此起彼伏。 – 2009-06-03 09:00:04

+0

看看我的soln ...即使時間軸分佈在你的xml中,而不是順序工作。 – 2009-06-03 09:26:19

+0

@Rashmi:你從哪裏開始將相同的時間線從一起分組?我沒有看到任何關於時間軸值不唯一的建議。 – AnthonyWJones 2009-06-03 09:33:57

回答

9

這是很容易在以下條件爲真(我假設它是)做:

  • 一個<competition>內的所有<timeline> s爲唯一
  • 只有<fixture>的權利之後的給定<timeline>屬於它
  • 沒有<fixture>未經<timeline>元件之前它

此XSLT 1。0溶液:

<xsl:stylesheet 
    version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
> 

    <xsl:key name="kFixture" 
      match="fixture" 
      use="generate-id(preceding-sibling::timeline[1])" 
    /> 

    <xsl:template match="data"> 
    <xsl:copy> 
     <xsl:apply-templates select="competition" /> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="competition"> 
    <xsl:copy> 
     <xsl:apply-templates select="timeline" /> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="timeline"> 
    <xsl:copy> 
     <xsl:attribute name="time"> 
     <xsl:value-of select="." /> 
     </xsl:attribute> 
     <xsl:copy-of select="key('kFixture', generate-id())" /> 
    </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

生產:

<data> 
    <competition> 
    <timeline time="10:00"> 
     <fixture>team a v team b</fixture> 
     <fixture>team c v team d</fixture> 
    </timeline> 
    <timeline time="12:00"> 
     <fixture>team e v team f</fixture> 
    </timeline> 
    <timeline time="16:00"> 
     <fixture>team g v team h</fixture> 
     <fixture>team i v team j</fixture> 
     <fixture>team k v team l</fixture> 
    </timeline> 
    </competition> 
</data> 

注意,使用<xsl:key>的匹配所有<fixture> s表示屬於( 「由前面」)給定<timeline>

稍微短一些,但不太明顯的解決辦法是修改的身份轉換:

<xsl:stylesheet 
    version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
> 

    <xsl:key name="kFixture" 
      match="fixture" 
      use="generate-id(preceding-sibling::timeline[1])" 
    /> 

    <xsl:template match="* | @*"> 
    <xsl:copy> 
     <xsl:apply-templates select="*[not(self::fixture)] | @*" /> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="timeline"> 
    <xsl:copy> 
     <xsl:attribute name="time"> 
     <xsl:value-of select="." /> 
     </xsl:attribute> 
     <xsl:copy-of select="key('kFixture', generate-id())" /> 
    </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 
0

嘗試類似的東西:

<xsl:template match="timeline"> 
    <timeline> 
      <xsl:attribute name="time" > 
        <xsl:value-of select="." /> 
      </xsl:attribute> 

      <xsl:apply-templates select="following-sibling::*[name()=fixture][1]" /> 

    </timeline> 
</xsl:template> 

<xsl:template match="fixture"> 
    <fixture> 
      <xsl:value-of select="." /> 
    </fixture> 
    <xsl:apply-templates select="following-sibling::*[name()=fixture][1]" /> 
</xsl:template> 
+0

它不明白下一個兄弟姐妹。相反,我使用以下兄弟:: * [1] – Xetius 2009-06-03 09:15:40

+0

下一個兄弟不是我認識的軸? – AnthonyWJones 2009-06-03 09:31:46

0

隨着給G ANDRIEU我不得不做出它只能得到下一個項目,而不是名單以下幫助:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 

    <xsl:template match="competition" > 

     <xsl:apply-templates select="timeline" /> 

    </xsl:template> 

    <xsl:template match="timeline"> 
     <timeline> 
      <xsl:attribute name="time" > 
       <xsl:value-of select="." /> 
      </xsl:attribute> 

      <xsl:apply-templates select="following-sibling::*[1]" mode="copy"/> 

     </timeline> 
    </xsl:template> 

    <xsl:template match="fixture" mode="copy"> 
     <fixture> 
      <xsl:value-of select="." /> 
     </fixture> 
     <xsl:apply-templates select="following-sibling::*[1]" mode="copy"/> 
    </xsl:template> 

    <xsl:template match="timeline" mode="copy" /> 

</xsl:stylesheet> 
1

摹ANDRIEU的解決方案不起作用,因爲不幸的是,沒有像'兄弟姐妹'那樣的軸線。

和替代的解決方案是以下幾點:

<xsl:template match="timeline"> 
<timeline> 
    <xsl:attribute name="time" > 
    <xsl:value-of select="." /> 
    </xsl:attribute> 

    <xsl:apply-templates select="following-sibling::*[local-name()='fixture' and position()=1]" /> 

</timeline> 
</xsl:template> 

<xsl:template match="fixture"> 
    <fixture> 
     <xsl:value-of select="." /> 
    </fixture> 
    <xsl:apply-templates select="following-sibling::*[local-name()='fixture' and position()=1]" /> 
</xsl:template> 
1

下面的XSLT將工作,即使相同的時間表分散在多個位置。對於例如在FOLL XML有2個條目時間表10:00

<?xml version="1.0" encoding="UTF-8"?> 
<data> 
    <competition> 
     <timeline>10:00</timeline> 
     <fixture>team a v team b</fixture> 
     <fixture>team c v team d</fixture> 
     <timeline>12:00</timeline> 
     <fixture>team e v team f</fixture> 
     <timeline>16:00</timeline> 
     <fixture>team g v team h</fixture> 
     <fixture>team i v team j</fixture> 
     <fixture>team k v team l</fixture> 
     <timeline>10:00</timeline> 
     <fixture>team a v team b new</fixture> 
     <fixture>team c v team d new</fixture> 
    </competition> 
</data> 

XSLT

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
    <xsl:key name="TimelineDistint" match="timeline" use="."/> 

    <xsl:template match="data"> 
     <xsl:apply-templates select="competition"/> 
    </xsl:template> 

    <xsl:template match="competition"> 
     <data> 
      <competition> 
       <xsl:for-each select="timeline[generate-id() = generate-id(key('TimelineDistint', .)[1])]"> 
        <timeline> 
         <xsl:variable name="varTimeline" select="."/> 
         <xsl:attribute name="time"><xsl:value-of select="normalize-space(.)"/></xsl:attribute> 
         <xsl:for-each select="../fixture[preceding::timeline[1] = $varTimeline]"> 
          <fixture> 
           <xsl:value-of select="normalize-space(.)"/> 
          </fixture> 
         </xsl:for-each> 
        </timeline> 
       </xsl:for-each> 
      </competition> 
     </data> 
    </xsl:template> 
</xsl:stylesheet> 

輸出

<?xml version="1.0" encoding="UTF-8"?> 
<data> 
    <competition> 
     <timeline time="10:00"> 
      <fixture>team a v team b</fixture> 
      <fixture>team c v team d</fixture> 
      <fixture>team a v team b new</fixture> 
      <fixture>team c v team d new</fixture> 
     </timeline> 
     <timeline time="12:00"> 
      <fixture>team e v team f</fixture> 
     </timeline> 
     <timeline time="16:00"> 
      <fixture>team g v team h</fixture> 
      <fixture>team i v team j</fixture> 
      <fixture>team k v team l</fixture> 
     </timeline> 
    </competition> 
</data> 
3

這裏是我的嘗試。我所做的簡化事物的一個假設是具有特定文本值的時間軸元素已經是唯一的。

<?xml version="1.0" encoding="UTF-8" ?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" encoding="UTF-8" /> 

    <xsl:template match="/data"> 
    <data> 
     <xsl:apply-templates select="competition" /> 
    </data> 
    </xsl:template> 

    <xsl:template match="competition"> 
    <xsl:for-each select="timeline"> 
     <timeline time="{text()}"> 
     <xsl:copy-of 
      select="./following-sibling::fixture[count(preceding-sibling::timeline[1] | current()) = 1]" /> 
     </timeline> 
    </xsl:for-each> 
    </xsl:template> 

</xsl:stylesheet> 

根據Tomalak的建議,編輯上述內容以使用current()代替變量。