用于生成树的XSLT递归



我们有一个描述树结构的输入文档:

<?xml version="1.0"?>
<html>
<mas>
    <row> <col>2</col><col>4</col>  </row>
    <row> <col>3</col> </row>
    <row> <col></col> </row>
    <row> <col>5</col><col>6</col>  </row>
    <row> <col></col> </row>
    <row> <col></col> </row>
 </mas>
</html>

我们想创建一个树。我们想要这样的输出文档:

<Transform id="b_1">
 <Transform id="b_2">
  <Transform id="b_3"/>
 </Transform>
 <Transform id="b_4">
  <Transform id="b_5"/>
  <Transform id="b_6"/>
 </Transform>
</Transform>

我有XSLT样式表:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
<xsl:template name="vetka">
 <xsl:param name="row"/> 
 <xsl:for-each select="html/mas/*[$row]/*" >  
  <xsl:variable name="col" select="position()"/>
  <xsl:variable name="num" select="//html/mas/*[$row]/*[$col]"/>
  <Transform>   
   <xsl:attribute name="id"><xsl:value-of select="concat('b_',$num)"/></xsl:attribute>   
   <xsl:call-template name="vetka">
    <xsl:with-param name="row" select="$num"/>
   </xsl:call-template>
  </Transform>
</xsl:for-each>
</xsl:template>
<xsl:template match="/">
<xsl:result-document href="str.txt">
  <xsl:call-template name="vetka">
   <xsl:with-param name="row" select='1'/>
  </xsl:call-template>
</xsl:result-document>
</xsl:template>
</xsl:stylesheet>

但是我们得到两个("b_2","b_4")。我认为,递归不是开始。为什么?

主要问题是这一行…

<xsl:for-each select="html/mas/*[$row]/*" > 

这第一次有效,因为您位于文档元素/上。但是当您递归地调用模板时,您现在位于col元素上,并且这个xsl:for-each将查找称为html的子元素。所以,你应该把它改成:

<xsl:for-each select="/html/mas/*[$row]/*" />

同样,当递归调用模板时,需要将row参数设置为一个数字。目前它是一个字符串(恰好包含一个数字的字符串)。

试试这个XSLT,我稍微简化了一下(因为您的num变量实际上只是当前col元素的值)

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template name="vetka">
 <xsl:param name="row"/> 
 <xsl:for-each select="//html/mas/*[$row]/*[. != '']" >  
  <xsl:variable name="num" select="."/>
  <Transform id="{concat('b_',$num)}">   
   <xsl:call-template name="vetka">
    <xsl:with-param name="row" select="number($num)"/>
   </xsl:call-template>
  </Transform>
</xsl:for-each>
</xsl:template>
<xsl:template match="/">
  <xsl:call-template name="vetka">
   <xsl:with-param name="row" select='1'/>
  </xsl:call-template>
</xsl:template>
</xsl:stylesheet>

这并不完全产生您想要的输出,但是我无法确定您的b_1来自哪里。

最新更新