XSL - 循环遍历XML中的子节点

时间:2010-01-27 10:16:25

标签: html xml xslt

我想循环遍历这样的XML文件:

<node>
  <cd name="td1">
    <data value="cd1-0" />
    <cd name="td2">
      <data value="cd1-1" />
    </cd>
    <cd name="td3">
      <data value="cd1-2" />
    </cd>
  </cd>
  <cd name="td4">
    <data value="cd2-0" />
  </cd>
</node>

这就是我的结果。

<html>  
  <table border="1">  
    <tr>  
      <td>cd1-0</td>  
      <td></td>  
    </tr>  
    <tr>  
      <td></td>  
      <td>cd1-1</td>  
    </tr>  
    <tr>  
      <td></td>  
      <td>cd1-2</td>  
    </tr>  
    <tr>  
      <td>cd2-0</td>  
      <td></td>  
    </tr>  
  </table>  
</html>

在本次考试中,我在节点cd上有2个级别。但水平可以是无限的。所以我需要某种递归循环函数。

3 个答案:

答案 0 :(得分:2)

这适用于任何级别的imbricated cd元素。

您必须修改位以生成<html>(和<head/><body>...</body>)结构,这可以在match='node'模板中。

它将跳过渲染不需要的空尾随<td/>

<强> XSL

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >

    <xsl:template match="node">
       <xsl:element name="table">
        <xsl:apply-templates />
        </xsl:element>
    </xsl:template>

    <xsl:template match="cd">   
        <xsl:element name="tr">
            <xsl:for-each select="ancestor::cd">
                <xsl:element name="td"/>
            </xsl:for-each>
            <xsl:element name="td">
                <xsl:value-of select="./data/@value" />
            </xsl:element>
        </xsl:element>
        <xsl:apply-templates />
    </xsl:template>

</xsl:stylesheet>

<强>输出

<table>
  <tr><td>cd1-0</td></tr>        <!-- Here the second <td/> is skipped -->
  <tr><td/><td>cd1-1</td></tr>
  <tr><td/><td>cd1-2</td></tr>
  <tr><td>cd2-0</td></tr>        <!-- Here the second <td/> is skipped -->
</table>

答案 1 :(得分:0)

您发送的XML看起来不像格式良好的XML。将此留给您,您可以在xslt中使用foreach元素。

例如:

<table>
<xsl:for-each select="node/cd">
<tr>
<td>
<xsl:value-of select="data/@value"/>
</td>
</tr>
</xsl:for-each>
</table>

点击此链接了解更多信息:http://www.w3schools.com/Xsl/xsl_for_each.asp

希望你明白了。

更新:感谢subtenante清理xml。 您可以使用模板来解决此问题

<xsl:template match="node">
 <html>
  <body>
   <table border="1">
      <xsl:apply-templates select="cd" />
   </table>
  </body>
 </html>
</xsl:template>

<xsl:template match="cd">
 <tr>
  <td>
   <xsl:value-of select="@name" />
  </td>
  <td>
   <xsl:value-of select="data/@value"/>
  </td>
 </tr> 

 <xsl:if test="cd">
  <xsl:apply-templates select="cd" />
 </xsl:if>
</xsl:template>

这将产生下表:

<table border="1">
<tbody>
<tr>
 <td>td1</td>
 <td>cd1-0</td>
</tr>
<tr>
 <td>td2</td>
 <td>cd1-1</td>
</tr>
<tr>
 <td>td3</td>
 <td>cd1-2</td>
</tr>
<tr>
 <td>td4</td>
 <td>cd2-0</td>
</tr>
</tbody></table>

提供的xslt需要稍微修改才能达到您想要的效果。如果你对这个很好。大。

来源:1

Ramjee

答案 2 :(得分:0)

一种方法:

<xsl:stylesheet 
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
  <!-- adapt output method and doctype to your needs -->
  <xsl:output 
    method="html" 
    doctype-system="http://www.w3.org/TR/html4/strict.dtd" 
    doctype-public="-//W3C//DTD HTML 4.01//EN" 
    indent="yes" 
  /> 

  <!-- the document root becomes html -->
  <xsl:template match="/">
    <html>
      <xsl:apply-templates select="*" />
    </html>
  </xsl:template>

  <!-- node becomes table -->
  <xsl:template match="node">
    <table border="1">
      <xsl:apply-templates select="*" />
    </table>
  </xsl:template>

  <!-- 1st level cd elements (children of node) go into first td -->
  <xsl:template match="node/cd">
    <tr>
      <td><xsl:value-of select="data/@value" /></td>
      <td />
    </tr>
  </xsl:template>

  <!-- 2nd level cd elements (children of cd) go into second td -->
  <xsl:template match="cd/cd">
    <tr>
      <td />
      <td><xsl:value-of select="data/@value" /></td>
    </tr>
  </xsl:template>

</xsl:stylesheet>