Gnarlund
Gnarlund

Reputation: 115

Group specific elements in tables with xslt 1.0

I am trying to transform the following code into 3 tables:

<bold>Hello</bold>
<bold>world</bold>
<p>Hello world!</p>
<bold>Please</bold>
<bold>help</bold>
<bold>me</bold>
<p>Please help me.</p>
<h1>This community is great<h1>
<bold>Thank</bold>
<bold>you</bold>
<bold>very</bold> 
<bold>much</bold>

The final result should look like this:

<table>
<th>NewHeader1<th>
<tr>
<td>Hello</td>
<td>world</td>
</tr>
</table>
<p>Hello world!</p>

<table>
<th>NewHeader2<th>
<tr>
<td>Please</td>
<td>help</td>
<td>me</td>
</tr>
</table>
<p>Please help me.</p>
<h1>This community is great.<h1>

<table>
<th>NewHeader3<th>
<tr>
<td>Thank</td>
<td>you</td>
<td>very</td>
<td>much</td>
</tr>
</table>

Unfortunately, I achieve only to put all the bold-elements in a single table. Thanks for your help!

Upvotes: 0

Views: 127

Answers (1)

michael.hor257k
michael.hor257k

Reputation: 117175

Given a well-formed XML input such as:

XML

<root>
    <bold>Hello</bold>
    <bold>world</bold>
    <p>Hello world!</p>
    <bold>Please</bold>
    <bold>help</bold>
    <bold>me</bold>
    <p>Please help me.</p>
    <h1>This community is great</h1>
    <bold>Thank</bold>
    <bold>you</bold>
    <bold>very</bold>
    <bold>much</bold>
</root>

you could use a technique known as sibling recursion:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="bold">
    <table>
        <th>
            <xsl:text>NewHeader</xsl:text>
            <xsl:number count="bold[not(preceding-sibling::*[1][self::bold])]"/>
        </th>
        <tr>
            <xsl:apply-templates select="." mode="cell"/>           
        </tr>
    </table>
</xsl:template>

<xsl:template match="bold" mode="cell">
    <td>
        <xsl:value-of select="."/>
    </td>
    <!-- sibling recursion -->
    <xsl:apply-templates select="following-sibling::*[1][self::bold]" mode="cell"/>         
</xsl:template>

<xsl:template match="bold[preceding-sibling::*[1][self::bold]]"/>

</xsl:stylesheet>

to produce:

Result

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <table>
      <th>NewHeader1</th>
      <tr>
         <td>Hello</td>
         <td>world</td>
      </tr>
   </table>
   <p>Hello world!</p>
   <table>
      <th>NewHeader2</th>
      <tr>
         <td>Please</td>
         <td>help</td>
         <td>me</td>
      </tr>
   </table>
   <p>Please help me.</p>
   <h1>This community is great</h1>
   <table>
      <th>NewHeader3</th>
      <tr>
         <td>Thank</td>
         <td>you</td>
         <td>very</td>
         <td>much</td>
      </tr>
   </table>
</root>

Upvotes: 2

Related Questions