2012-06-21 76 views
3

我正試圖圍繞這一點來解決這個問題,我認爲最簡單的解釋方法就是向您展示下面。我已經看過this,但它並不總是適用,因爲我有單獨的項目也在最後匹配。XSLT將兩個兄弟姐妹內部的元素分組

貌似棘手的部分是Whatever3到Whatever6,然後Whatever7和Whatever8,然後最後Whatever9的新位置 - 他們需要分組和保持原始序列。 (忽略我的命名,有沒有辦法使用xsl:sort)

我已經考慮過xsl:for-each與xsl:如果裏面,但問題是你不能保證有多少「組」與「非」組「的項目。

謝謝!

XML

<root> 
    <item> 
     <position>1</position> 
     <label>Whatever1</label> 
    </item> 
    <item> 
     <position>2</position> 
     <label>Whatever2</label> 
    </item> 
    <item> 
     <position>3</position> 
     <label>Whatever3</label> 
     <marker id="unique1">start_group</marker> 
    </item> 
    <item> 
     <position>4</position> 
     <label>Whatever4</label> 
    </item> 
    <item> 
     <position>5</position> 
     <label>Whatever5</label> 
    </item> 
    <item> 
     <position>6</position> 
     <label>Whatever6</label> 
     <marker>last_in_group</marker> 
    </item> 
    <item> 
     <position>7</position> 
     <label>Whatever7</label> 
     <marker id="unique2">start_group</marker> 
    </item> 
    <item> 
     <position>8</position> 
     <label>Whatever8</label> 
     <marker>last_in_group</marker> 
    </item> 
    <item> 
     <position>9</position> 
     <label>Whatever9</label> 
    </item> 
</root> 

結果

<structure> 
    <item> 
     <position>1</position> 
     <label>Whatever1</label> 
    </item> 
    <item> 
     <position>2</position> 
     <label>Whatever2</label> 
    </item> 
    <group position="3" id="unique1"> 
     <item> 
      <position>1</position> 
      <label>Whatever3</label> 
     </item> 
     <item> 
      <position>2</position> 
      <label>Whatever4</label> 
     </item> 
     <item> 
      <position>3</position> 
      <label>Whatever5</label> 
     </item> 
     <item> 
      <position>4</position> 
      <label>Whatever6</label> 
     </item> 
    </group> 
    <group position="4" id="uniqueid2"> 
     <item> 
      <position>1</position> 
      <label>Whatever7</label> 
     </item> 
     <item> 
      <position>2</position> 
      <label>Whatever8</label> 
     </item> 
    </group> 
    <item> 
     <position>**5**</position> 
     <label>Whatever9</label> 
    </item> 
</structure> 

======================

這裏是我的迄今爲止,唯一的問題是(除了雜亂無章),無論是在集團以外的其他地區。

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

    <xsl:template match="root"> 
    <structure> 
    <xsl:apply-templates select="item[not(marker)] | item[marker='start_group']"/> 
    </structure> 
</xsl:template> 

    <xsl:template match="item[marker='start_group']"> 
    <group> 
    <xsl:variable name="currentPosition" select="number(position/text())"/> 
    <xsl:variable name="lastGroup" select="count(following-sibling::*[local-name() = 'item' and marker='last_in_group'][1]/preceding-sibling::*) + 1"/> 

    <xsl:attribute name="position"> 
     <xsl:value-of select="$currentPosition"/> 
    </xsl:attribute> 
    <xsl:attribute name="id"> 
     <xsl:value-of select="marker/@id"/> 
    </xsl:attribute> 

    <item> 
    <position><xsl:value-of select="number(position/text()) - $currentPosition + 1"/></position> 
    <label><xsl:value-of select="label/text()"/></label> 
    </item> 

    <!-- position() gets reset in for-loop, so need to adjust with outer position --> 
    <xsl:for-each select="following-sibling::item[(position() + $currentPosition) &lt;= $lastGroup]"> 
     <item> 
       <position><xsl:value-of select="number(position/text()) - $currentPosition + 1"/></position> 
       <label><xsl:value-of select="label/text()"/></label> 
     </item> 
    </xsl:for-each> 
    </group> 
</xsl:template> 

    <xsl:template match="item[not(marker)]"> 
    <item> 
    <position><xsl:value-of select="position/text()"/></position> 
    <label><xsl:value-of select="label/text()"/></label> 
    </item> 
</xsl:template> 

</xsl:stylesheet> 
+0

你試過了什麼?除了考慮xsl:for-each和xsl:如果當然。請發佈您到目前爲止所提供的XSLT。 – toniedzwiedz

+0

給我一點點,我需要將筆記本電腦切換到我的XSLT所在的位置,並將其從我真正的XML格式轉換爲我在上面做的模型。 –

+0

已編輯原創帖子。 –

回答

3

I. XSLT 1.0解

該轉化

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

<xsl:key name="kFollowing" 
    match="item[not(marker[. = 'start_group']) 
      and 
       preceding-sibling::*[marker][1]/marker = 'start_group' 
      ]" 
    use="generate-id(preceding-sibling::* 
        [marker[. = 'start_group']] 
        [1])"/> 

<xsl:template match="node()|@*"> 
    <xsl:copy> 
    <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="item[marker[. = 'start_group']]"> 
    <group position="{1 +count(preceding-sibling::*[. = 'start_group'])}" 
    id="{marker/@id}"> 
    <xsl:copy-of select=".|key('kFollowing', generate-id())"/> 
    </group> 
</xsl:template> 

<xsl:template match= 
    "item[not(marker[. = 'start_group']) 
     and 
     preceding-sibling::*[marker][1]/marker = 'start_group' 
     ]"/> 
</xsl:stylesheet> 

當所提供的XML文檔應用:

<root> 
    <item> 
     <position>1</position> 
     <label>Whatever1</label> 
    </item> 
    <item> 
     <position>2</position> 
     <label>Whatever2</label> 
    </item> 
    <item> 
     <position>3</position> 
     <label>Whatever3</label> 
     <marker id="unique1">start_group</marker> 
    </item> 
    <item> 
     <position>4</position> 
     <label>Whatever4</label> 
    </item> 
    <item> 
     <position>5</position> 
     <label>Whatever5</label> 
    </item> 
    <item> 
     <position>6</position> 
     <label>Whatever6</label> 
     <marker>last_in_group</marker> 
    </item> 
    <item> 
     <position>7</position> 
     <label>Whatever7</label> 
     <marker id="unique2">start_group</marker> 
    </item> 
    <item> 
     <position>8</position> 
     <label>Whatever8</label> 
     <marker>last_in_group</marker> 
    </item> 
    <item> 
     <position>9</position> 
     <label>Whatever9</label> 
    </item> 
</root> 

產生想要的,正確的結果:

<root> 
    <item> 
     <position>1</position> 
     <label>Whatever1</label> 
    </item> 
    <item> 
     <position>2</position> 
     <label>Whatever2</label> 
    </item> 
    <group position="1" id="unique1"> 
     <item> 
     <position>3</position> 
     <label>Whatever3</label> 
     <marker id="unique1">start_group</marker> 
     </item> 
     <item> 
     <position>4</position> 
     <label>Whatever4</label> 
     </item> 
     <item> 
     <position>5</position> 
     <label>Whatever5</label> 
     </item> 
     <item> 
     <position>6</position> 
     <label>Whatever6</label> 
     <marker>last_in_group</marker> 
     </item> 
    </group> 
    <group position="1" id="unique2"> 
     <item> 
     <position>7</position> 
     <label>Whatever7</label> 
     <marker id="unique2">start_group</marker> 
     </item> 
     <item> 
     <position>8</position> 
     <label>Whatever8</label> 
     <marker>last_in_group</marker> 
     </item> 
    </group> 
    <item> 
     <position>9</position> 
     <label>Whatever9</label> 
    </item> 
</root> 

II。 XSLT 2.0溶液

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="node()|@*"> 
    <xsl:copy> 
    <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="/*"> 
    <root> 
    <xsl:for-each-group select="item" group-starting-with= 
    "*[marker eq 'start_group' 
    or 
     not(marker) 
    and 
     preceding-sibling::*[marker][1]/marker eq 'last_in_group' 
    ] 
    "> 
    <xsl:choose> 
     <xsl:when test="current-group()[1]/marker"> 
       <group position= 
       "{1 +count(current-group()[1] 
          /preceding-sibling::* 
            [marker = 'start_group'])}" 
       id="{marker/@id}"> 
       <xsl:apply-templates select="current-group()"/> 
       </group> 
     </xsl:when> 
     <xsl:otherwise> 
     <xsl:apply-templates select="current-group()"/> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:for-each-group> 
    </root> 
</xsl:template> 
</xsl:stylesheet> 

當該XSLT 2.0變換對相同的XML文檔(以上)應用中,相同的正確的結果產生

+0

謝謝迪米特雷!完美,你很出色。 –

+0

在XSLT 1.0版本中我只需要更改一件事 - xsl:copy-of對項目不起作用,因爲我需要刪除一些元素(標記元素不應出現在輸出中)。 –

+0

@JonathonHowey:不客氣。不斷提出這些具有挑戰性 –