XSLT处理所有节点,直到具有特定名称的节点

时间:2017-11-20 10:31:24

标签: xml xslt xslt-1.0

我有以下xml结构:

    <?xml version="1.0"?>
<items>
    <item/>
    <desc/>
    <desc2/>
    <desc3/>
    <price1/>
    <info/>
    <info/>
    <info2/>
    <item/>
    <desc/>
    <price1/>
    <price2/>
    <price3/>
    <info1/>
    <anotheriinfo/>
    <specialinfo/>
    <item/>
    <desc/>
    <price1/>
</items>

其中<item>不是以下节点的父级。 我需要将不同的项目与相应的信息和定价分组。有没有办法在下一个<item>之前选择<item>和所有后续节点并应用一些logig?或者将它们分组为

   <?xml version="1.0" encoding="UTF-8"?>
<items>
  <item>
    <desc/>
    <desc2/>
    <desc3/>
    <price1/>
    <info/>
    <info/>
    <info2/>
  </item>
  <item>
    <desc/>
    <price1/>
    <price2/>
    <price3/>
    <info1/>
    <anotheriinfo/>
    <specialinfo/>
  </item>
  <item>
    <desc/>
    <price1/>
  </item>
</items>

我需要使用XSLT 1.0

2 个答案:

答案 0 :(得分:2)

您可能想要阅读并在此处应用的三种技巧。

  • 如果你想要的只是item元素显示之前的空白行(如#34所示;或者将它们分组为......&#34;),请编写样式表发出那个。

  • 阅读Muenchian分组;要分组的值是名为item的前一个兄弟的数量(对于名为item的节点)或者名为item的前一个兄弟的数量加一(item元件)。

  • 学习通过首先在其子项上调用模板apply-templates然后在其右边兄弟上调用来执行树遍历。在这种情况下,基本模式是

    <xsl:template match="items">
      <xsl:apply-templates match="item"/>
    </
    
    <xsl:template match="item">  
      <xsl:copy>
        <!-- handle descendants, if your current items have any ... --> 
        <xsl:apply-templates match="@*|node()"/>
        <!-- bring right siblings into the content ... -->
        <xsl:apply-templates match="following-sibling::*[1]" 
             mode="group-nodes"/>
      </
    </
    
    <xsl:template match="*" mode="group-nodes" priority="1">
      <!-- 1 handle this element -->
      <!-- modify next line if items elements can nest ... -->
      <xsl:copy-of select="."/>
    
      <!-- 2 handle next sibling -->
      <xsl:apply-templates match="following-sibling::*[1]" 
             mode="group-nodes"/>
      </
    </
    
    <xsl:template match="item" mode="group-nodes" priority="10"/>
    

答案 1 :(得分:1)

我喜欢Sperberg-McQueens与Muenchian分组的解决方案。我采用了一种完全不同的方法(再次!!),基于position()以及产生所需结果的后续兄弟姐妹的数量。只是想分享一下:

<xsl:template match="items">
    <xsl:copy>
        <!-- total number of items -->
        <xsl:variable name="countItems" select="count(item)"/>
        <!-- edit: copy elements before first item -->
        <xsl:copy-of select="*[following-sibling::item[$countItems]]"/>
        <xsl:for-each select="item">
            <!-- position of current item -->
            <xsl:variable name="position" select="position()"/>
            <xsl:choose>
                <xsl:when test="following-sibling::item">
                    <xsl:copy>
                        <!-- get all elements before next item -->
                        <!-- = all elements followed by (total items minus current position) items -->
                        <xsl:apply-templates select="following-sibling::*[following-sibling::item[$countItems - $position]]"/>
                    </xsl:copy>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:copy>
                        <xsl:apply-templates select="following-sibling::*"/>
                    </xsl:copy>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>

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