2011-09-20 55 views
3

我試圖找出一個xslt應該是相當簡單的,但給我一些悲傷。基本上,我想先從下面的XML ...XSLT包裝後續兄弟元素,具體取決於計數

<?xml version="1.0" encoding="UTF-8"?> 
<TEST> 
    <OBR> 
     <OBR-1>obr1</OBR-1> 
    </OBR> 
    <OBX> 
     <OBX-1>obx1</OBX-1> 
    </OBX> 
    <OBX> 
     <OBX-1>obx2</OBX-1> 
    </OBX> 
    <OBR> 
     <OBR-1>obr2</OBR-1> 
    </OBR> 
    <OBX> 
     <OBX-1>obx2-1</OBX-1> 
    </OBX> 
    <OBX> 
     <OBX-1>obx2-2</OBX-1> 
    </OBX> 
    <OBR> 
     <OBR-1>obr3</OBR-1> 
    </OBR> 
    <OBX> 
     <OBX-1>obx3-1</OBX-1> 
    </OBX> 
    <OBX> 
     <OBX-1>obx3-2</OBX-1> 
    </OBX> 
</TEST> 

,並與下面的結束......

<?xml version="1.0" encoding="UTF-8"?> 
<TEST> 
    <OBR> 
     <OBR-1>obr1</OBR-1> 
    </OBR> 
    <OBX> 
     <OBX-1>obx1</OBX-1> 
    </OBX> 
    <OBX> 
     <OBX-1>obx2</OBX-1> 
    </OBX> 
    <SENSITIVITY> 
     <OBR> 
      <OBR-1>obr2</OBR-1> 
     </OBR> 
     <OBX> 
      <OBX-1>obx2-1</OBX-1> 
     </OBX> 
     <OBX> 
      <OBX-1>obx2-2</OBX-1> 
     </OBX> 
     <OBR> 
      <OBR-1>obr3</OBR-1> 
     </OBR> 
     <OBX> 
      <OBX-1>obx3-1</OBX-1> 
     </OBX> 
     <OBX> 
      <OBX-1>obx3-2</OBX-1> 
     </OBX> 
    </SENSITIVITY> 
</TEST> 

基本上,只要達到第二OBR元素,它,以及任何以下的OBR和OBX必須包裝在SENSITIVITY元素中。最初的xml可能包含或不包含多個OBR。

謝謝。

+0

好問題,+1。使用最基本和最強大的XSLT設計模式很容易實現 - 覆蓋身份規則/模板。 –

回答

3

這種簡單和短期轉型

<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:template match="node()|@*" name="identity"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="OBR[2]"> 
    <SENSITIVITY> 
    <xsl:apply-templates select=".|following-sibling::node()" mode="inGroup"/> 
    </SENSITIVITY> 
</xsl:template> 

<xsl:template match="node()" mode="inGroup"> 
    <xsl:call-template name="identity"/> 
</xsl:template> 

<xsl:template match="*[count(preceding-sibling::OBR) >1]"/> 
</xsl:stylesheet> 

時所提供的XML文檔應用:

<TEST> 
    <OBR> 
     <OBR-1>obr1</OBR-1> 
    </OBR> 
    <OBX> 
     <OBX-1>obx1</OBX-1> 
    </OBX> 
    <OBX> 
     <OBX-1>obx2</OBX-1> 
    </OBX> 
    <OBR> 
     <OBR-1>obr2</OBR-1> 
    </OBR> 
    <OBX> 
     <OBX-1>obx2-1</OBX-1> 
    </OBX> 
    <OBX> 
     <OBX-1>obx2-2</OBX-1> 
    </OBX> 
    <OBR> 
     <OBR-1>obr3</OBR-1> 
    </OBR> 
    <OBX> 
     <OBX-1>obx3-1</OBX-1> 
    </OBX> 
    <OBX> 
     <OBX-1>obx3-2</OBX-1> 
    </OBX> 
</TEST> 

產生想要的,正確的結果

<TEST> 
    <OBR> 
     <OBR-1>obr1</OBR-1> 
    </OBR> 
    <OBX> 
     <OBX-1>obx1</OBX-1> 
    </OBX> 
    <OBX> 
     <OBX-1>obx2</OBX-1> 
    </OBX> 
    <SENSITIVITY> 
     <OBR> 
     <OBR-1>obr2</OBR-1> 
     </OBR> 
     <OBX> 
     <OBX-1>obx2-1</OBX-1> 
     </OBX> 
     <OBX> 
     <OBX-1>obx2-2</OBX-1> 
     </OBX> 
     <OBR> 
     <OBR-1>obr3</OBR-1> 
     </OBR> 
     <OBX> 
     <OBX-1>obx3-1</OBX-1> 
     </OBX> 
     <OBX> 
     <OBX-1>obx3-2</OBX-1> 
     </OBX> 
    </SENSITIVITY> 
</TEST> 

說明

  1. identity rule副本的每個節點 「原樣」。

  2. 模板覆蓋作爲其父母的第二個OBR孩子的OBR元素的標識規則。這裏我們生成包裝元素SENSITIVITY,並在特殊的mode中處理所有後續節點,名爲"inGroup"

  3. 匹配"ingroup"模式中任何元素的模板只是調用標識規則。或者,在這裏我們可以簡單地使用<xsl:copy-of select="."/>指令。

  4. 爲了抑制身份模板複製到輸出(正常,匿名模式)第二個OBR後面的元素,我們指定了與任何此類元素相匹配的另一個模板規則並且具有空的主體,這有效地阻止了任何此類元素從被複制到輸出。該模板覆蓋並抑制身份規則。

+0

+1很好的解釋 – user364939

+0

@ user364939:不客氣。 –