分析非重复父节点中的重复子元素



我有以下输入xml,想知道XSLT是否可以处理这样的转换。如果可以,如何实现?

输入xml:

<foo>
  <bar>
    <A>xxx</A>
    <B>yyy</B>
    <C>zzz</C>
    <A>aaa</A>
    <B>bbb</B>
    <C>ccc</C>
     ...
     ..
  </bar>
</foo>

输出xml:

<data>
   <A>xxx</A>
   <B>yyy</B>
   <C>zzz</C>
</data>
<data>
   <A>aaa</A>
   <B>bbb</B>
   <C>ccc</C>
</data>
....

在上面的例子中可能有更多重复的A、B、C节点。由于重复不在重复父节点中,因此不可能分别使用。我一直在探索每个小组的选项,但不确定这是否适用。如有任何建议,不胜感激。

使用XSLT1.0,以下解决方案正在使用具有6个元素的示例XML进行工作测试:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/*">
 <xsl:apply-templates select="/foo/bar"/>
</xsl:template>
<xsl:template match="bar">
 <xsl:for-each select="*/node()">
   <xsl:if test="(position()-1) mod(3) = 0">
    <data>
     <xsl:call-template  name="grouping">
      <xsl:with-param name="position" select="position()"/>
      <xsl:with-param name="amount" select="3"/>
     </xsl:call-template>
    </data>
   </xsl:if>
  </xsl:for-each>
</xsl:template>
<xsl:template  name="grouping">
<xsl:param name="position" select="0"/>
<xsl:param name="amount" select="0"/>
<xsl:copy-of select="//bar/*[$position]"/>
   <xsl:if test="$amount > $position or   ($position mod(3) > 0)">
    <xsl:call-template  name="grouping">
      <xsl:with-param name="position" select="$position + 1"/>
      <xsl:with-param name="amount" select="$amount"/>
    </xsl:call-template>
   </xsl:if>
 </xsl:template>
</xsl:stylesheet>

结果:

<?xml version="1.0" encoding="UTF-8"?>
<data>
   <A>xxx</A>
   <B>yyy</B>
   <C>zzz</C>
</data>
<data>
   <A>aaa</A>
   <B>bbb</B>
   <C>ccc</C>
</data>

简而言之,在模板匹配"栏"中,所有元素节点都在中处理

<xsl:for-each select="*/node()">

通过使用<xsl:if test="(position()-1) mod(3) = 0">(对于第一个节点和每第三个节点为0),调用名为"grouping"的模板来提供3个节点的生成组。调用此模板时,参数为position(当前节点的位置)和amount(每组中要复制的节点数量)
分组模板复制当前节点<xsl:copy-of select="//bar/*[$position]"/>-检查是否已经生成了3个节点<xsl:if test="$amount > $position or ($position mod(3) > 0)">-并再次调用自己,将位置作为计数器递增,因此将复制下一个节点
只是为了防止这一点不明显——将为$amount > $position调用分组模板,因此将复制前3个节点,并为$position mod(3) > 0调用所有后续节点,只要它不是3的倍数。如果xml中有第7个元素,那么它将作为data-组中的单个元素进行复制。

正如您最初所想,xsl:for-each-group将是完美的;使用group-starting-with属性。

XML输入

<foo>
    <bar>
        <A>xxx</A>
        <B>yyy</B>
        <C>zzz</C>
        <A>aaa</A>
        <B>bbb</B>
        <C>ccc</C>
        <A>111</A>
        <B>222</B>
        <C>333</C>
    </bar>
</foo>

XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="/*">
        <xsl:for-each-group select="bar/*" group-starting-with="A">
            <data>
                <xsl:apply-templates select="current-group()"/>
            </data>
        </xsl:for-each-group>       
    </xsl:template>
</xsl:stylesheet>

XML输出(格式不符合原始问题中的规定)

<data>
   <A>xxx</A>
   <B>yyy</B>
   <C>zzz</C>
</data>
<data>
   <A>aaa</A>
   <B>bbb</B>
   <C>ccc</C>
</data>
<data>
   <A>111</A>
   <B>222</B>
   <C>333</C>
</data>

相关内容

  • 没有找到相关文章

最新更新