XSLT根据匹配条件将XML拆分为组

时间:2017-03-08 14:04:12

标签: xml xslt

我陷入了XSLT的一个问题: 我的xml是:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<nums>
  <num>02</num>
  <num>02</num>
  <num>03</num>
  <num>04</num>
  <num>05</num>
  <num>06</num>
  <num>06</num>
  <num>08</num>
  <num>09</num>
  <num>10</num>
</nums>

My Current XSLT是:

<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:param name="pGroupSize" select="3"/>

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

 <xsl:template match="/*">
  <nums>
   <xsl:apply-templates select=
       "num[position() mod $pGroupSize = 1]"/>
  </nums>
 </xsl:template>

 <xsl:template match="num">
  <group>
   <xsl:copy-of select=
    ".|following-sibling::*
              [not(position() > $pGroupSize -1)]"/>
  </group>
 </xsl:template>
</xsl:stylesheet>

我目前的输出: 无论节点值如何,都拆分xml。

<nums>
   <group>
      <num>02</num>
      <num>02</num>
      <num>03</num>
   </group>
   <group>
      <num>04</num>
      <num>05</num>
      <num>06</num>
   </group>
   <group>
      <num>07</num>
      <num>08</num>
      <num>09</num>
   </group>
   <group>
      <num>10</num>
   </group>
</nums>

我的预期输出XML: 首先检查是否存在与最后一个节点匹配的节点,如果是,则包括它们,否则排除它们。

<nums>
   <group>
      <num>02</num>
      <num>02</num>
      <num>03</num>
   </group>
   <group>
      <num>04</num>
      <num>05</num>
      <num>06</num>
      <num>06</num>
   </group>
   <group>
      <num>08</num>
      <num>09</num>
      <num>10</num>
   </group>
</nums>

1 个答案:

答案 0 :(得分:0)

我认为你可能想要使用兄弟递归来解决这个问题,或者,如果XSLT 3.0可用,则使用xsl:iterate

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:math="http://www.w3.org/2005/xpath-functions/math"
    exclude-result-prefixes="xs math"
    version="3.0">

    <xsl:output indent="yes"/>

    <xsl:param name="pGroupSize" as="xs:integer" select="3"/>

    <xsl:template match="/*">
        <xsl:copy>
            <xsl:iterate select="*">
                <xsl:param name="group" as="element()*" select="()"/>
                <xsl:param name="last" as="element()?" select="()"/>
                <xsl:on-completion>
                    <xsl:if test="$group">
                        <group>
                            <xsl:copy-of select="$group"/>
                        </group>
                    </xsl:if>
                </xsl:on-completion>
                <xsl:if test="count($group) ge $pGroupSize and . != $last">
                    <group>
                        <xsl:copy-of select="$group"/>
                    </group>
                </xsl:if>
                <xsl:next-iteration>
                    <xsl:with-param name="group"
                        select="if (count($group) ge $pGroupSize and . != $last)
                                then .
                                else ($group, .)"/>
                    <xsl:with-param name="last"
                        select="if (count($group) ge $pGroupSize and . = $last) then $last else ."/>
                </xsl:next-iteration>
            </xsl:iterate>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>