XSLT基于其位置重复打印节点的值

时间:2015-02-25 12:03:27

标签: xml xslt xslt-1.0 xslt-2.0

我必须在xslt 1.0或xslt 2.0中转换此示例xml 源XML

<root>
    <group>
        <subgroup>
            <name>AAA1</name>
        </subgroup>
        <subgroup>
            <name>AAA2</name>
        </subgroup>
        <subgroup>
            <name>AAA3</name>
       </subgroup>
    </group>
 <group>
        <subgroup>
            <name>BB1</name>
        </subgroup>
        <subgroup>
            <name>BB2</name>
        </subgroup>
        <subgroup>
            <name>BB3</name>
       </subgroup>
    </group>
</root>

必需的XML输出

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <group>AAA1|BB1|AAA2|BB2|AAA3|BB3</group>
</root>

我尝试了以下xslt:

XSLT

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" />
    <xsl:template match="root">
    <root>
      <group>
       <xsl:for-each select="group">
          <xsl:for-each select="subgroup">
            <xsl:choose>
            <xsl:when test="position() != last()">
            <xsl:value-of select="name" /><xsl:text>|</xsl:text>
            </xsl:when>
            <xsl:otherwise>
               <xsl:value-of select="name" />
            </xsl:otherwise>
             </xsl:choose> 
          </xsl:for-each>
       </xsl:for-each>
       </group>
    </root>
</xsl:template>
</xsl:stylesheet>

当前输出

<?xml version="1.0" encoding="UTF-8"?>
<root>
<group>AAA1|AAA2|AAA3BB1|BB2|BB3</group>
</root>

我该怎么做?我应该以递归方式创建模板吗?

2 个答案:

答案 0 :(得分:1)

您只需处理一个spec元素集,然后按位置从另一个集合中提取相应的spec

<root>
  <group>
    <xsl:for-each select="group[1]/spec">
      <xsl:variable name="pos" select="position()"/>
      <xsl:for-each select="../../group">
        <!-- put a | in front of everything but the first spec in the first group -->
        <xsl:if test="$pos &gt; 1 or position() &gt; 1">|</xsl:if>
        <xsl:value-of select="spec[$pos]/name" />
      </xsl:for-each>
    </xsl:for-each>
  </group>
</root>

XSLT 2.0版本:在2.0中,您只需使用一个value-of

即可
<group>
  <xsl:value-of select="for $n in 1 to count(group[1]/spec)
                        return (group/spec[$n]/name)" separator="|" />
</group>

答案 1 :(得分:0)

想出了这个:

选择除第一组之外的所有其他组,然后迭代第一组的所有规格,同时从所有其他组中获取相应的规格

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" />
  <xsl:template match="root">
    <root>
      <group>
        <xsl:variable name="firstExcludeGroups" select="//group[position()!=1]"/>
        <xsl:variable name="firstGroup" select="//group[position()=1]"/>
        <xsl:for-each select="$firstGroup/spec">
          <xsl:value-of select="name"/>
          <xsl:text>|</xsl:text>
          <xsl:variable name="curPosition" select="position()"/>
          <xsl:for-each select="$firstExcludeGroups/spec">
            <xsl:if test="$curPosition=position()">
              <xsl:value-of select="name"/>
            </xsl:if>
          </xsl:for-each>
        </xsl:for-each>
      </group>
    </root>
  </xsl:template>
</xsl:stylesheet>