2011-09-20 54 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:不客气。 –