XSL - Passing through Nodes in XML

I want the loop through the XML file to look like this:

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

This is the result of what I am.

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

In this example, I have 2 levels on node cd. But the level can be infinite. So I need some kind of recursive loop function.

+3
source share
3 answers

This will work with any level of items cd.

You need to change the bit to create the structure <html>(s <head/><body>...</body>), it may be in the template match='node'.

He will skip empty trailing <td/>, which is not needed for rendering.

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>

Output

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

XML, , XML. , foreach xslt.

:

<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

0

One way to do this:

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

Source: https://habr.com/ru/post/1730182/


All Articles