【问题标题】:XSL - loop through sub nodes in XMLXSL - 遍历 XML 中的子节点
【发布时间】:2010-01-27 10:16:25
【问题描述】:

我想遍历一个如下所示的 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 个级别。但是级别可以是无限的。所以我需要某种递归循环函数。

【问题讨论】:

  • 提示:模板匹配="node/cd"

标签: html xml xslt


【解决方案1】:

这适用于任何级别的重叠式cd 元素。

您必须稍作修改以生成&lt;html&gt;(和&lt;head/&gt;&lt;body&gt;...&lt;/body&gt;)结构,这可以在match='node' 模板中。

它将跳过渲染不需要的空尾 &lt;td/&gt;

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>

【讨论】:

    【解决方案2】:

    一种方法:

    <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>
    

    【讨论】:

      【解决方案3】:

      您发送的 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

      拉姆吉

      【讨论】:

      • 最后你不需要那个xsl:if 测试。 &lt;xsl:apply-templates select="cd"/&gt; 只有在有一个或多个子 cd 元素时才会做任何事情;检查是否有第一个是多余的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-09
      • 1970-01-01
      • 2011-09-11
      相关资源
      最近更新 更多