1

I developed a java based command line utility that transform an xml into another xml file and generate HTML. In this program I used SAX parser to read the content of source xml into my java object then use JAXB to generate the XML. Right now I'm creating the HTMl file by populating a string for HTML content but it results in hardcoded html codes inside my java class. Based on my research I can do XML to HTML conversion using XSLT. I am new to XSLT. Can anyone help me? Please see samples below. Thanks

XML input:

<Groups>
   <Group>
    <GroupName>GroupA</GroupName>
    <Role>
        <RoleName>Correspondence Team B</RoleName>
        <Functions>
            <Function>CT2 Work</Function>
            <Function>HOL01_My Work</Function>
            <Function>HOL02_My Work</Function>
        </Functions>
    </Role>
</Group>

 <GroupName>GroupB</GroupName>
    <Role>
        <RoleName>Customer Service Rep</RoleName>
        <Functions>
            <Function>CSR Work</Function>
            <Function>HOL01_My Work</Function>
        </Functions>
    </Role>
</Group>
<Group>
    <GroupName>GroupB</GroupName>
    <Role>
        <RoleName>Dispute Advisor</RoleName>
        <Functions>
            <Function>DA Work</Function>
            <Function>HOL01_My Work</Function>
        </Functions>
    </Role>
</Group>
<Group>
    <GroupName>GroupA</GroupName>
    <Role>
        <RoleName>Correspondence Team</RoleName>
        <Functions>
            <Function>CT Work</Function>
            <Function>HOL01_My Work</Function>
        </Functions>
    </Role>
</Group>

<Group>
    <GroupName>GroupB</GroupName>
    <Role>
        <RoleName>Correspondence Team B</RoleName>
        <Functions>
            <Function>CT2 Work</Function>
            <Function>HOL01_My Work</Function>
            <Function>HOL02_My Work</Function>
        </Functions>
    </Role>
</Group>

Desired Html table format:

<table border=1>
    <tr>
        <th>Group Name</th>
        <th>Role Name</th>
        <th>Function Names</th>
    </tr>
    <tr>
        <td rowspan=5>Group A</td>
        <td rowspan=2>Correspondence Team</td>
        <td>CT Work</td>
    </tr>
    <tr>
        <td>HOL01_My Work</td>
    </tr>
    <tr>
        <td rowspan=3>Correspondence Team B</td>
        <td>CT Work</td>
    </tr>
    <tr>
        <td>HOL01_My Work</td>
    </tr>
    <tr>
        <td>HOL01_My Work</td>
    </tr>
    <tr>
        <td rowspan=0>Group B</td>
        <td rowspan=2>Customer Service Rep</td>
        <td>CSR Work</td>
    </tr>
    <tr>
        <td>HOL01_My Work</td>
    </tr>
    <tr>
        <td rowspan=2>Dispute Advisor</td>
        <td>DA Work</td>
    </tr>
    <tr>
        <td>HOL01_My Work</td>
    </tr>
    <tr>
        <td rowspan=2>Correspondence Team</td>
        <td>CT Work</td>
    </tr>
    <tr>
        <td>HOL01_My Work</td>
    </tr>
</table>
2
  • 1
    "Can anyone help me?" - with what? Please be more specific. Commented Oct 9, 2012 at 9:07
  • This looks like a grouping problem to me, which is best tackled with XSLT 2.0 and Saxon 9 (saxon.sourceforge.net/#F9.4HE) these days. Are you able or willing to use XSLT 2.0? Or do you want to use the XSLT 1.0 processor that is part of the Sun/Oracle JRE? Commented Oct 9, 2012 at 10:10

1 Answer 1

4

Assuming XSLT 2.0 (which you can run with Java with the help of Saxon 9) you can use a stylesheet like

<xsl:stylesheet 
  version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="xs">

<xsl:output method="html" indent="yes" version="5.0"/>

<xsl:template match="/">
  <html lang="en">
    <head>
      <title>Test</title>
    </head>
    <body>
      <h1>Test</h1>
      <xsl:apply-templates/>
    </body>
  </html>
</xsl:template>


<xsl:template match="Groups">
  <table frame="border" rules="all">
    <thead>
      <th>Group Name</th>
      <th>Role Name</th>
      <th>Function Names</th>
    </thead>
    <tbody>
      <xsl:variable name="groups" as="element(group)*">
        <xsl:for-each-group select="Group" group-by="GroupName">
          <group name="{current-grouping-key()}" size="{count(current-group()/Role/Functions/Function)}">
            <xsl:for-each-group select="current-group()" group-by="Role/RoleName">
              <role name="{current-grouping-key()}" size="{count(current-group()/Role/Functions/Function)}">
                <xsl:copy-of select="current-group()/Role/Functions/Function"/>
              </role>
            </xsl:for-each-group>
          </group>
        </xsl:for-each-group>
      </xsl:variable>
      <xsl:apply-templates select="$groups/role/Function"/>
    </tbody>
  </table>
</xsl:template>

<xsl:template match="group/role/Function">
  <tr>
    <xsl:apply-templates select="." mode="group"/>
    <xsl:apply-templates select="." mode="role"/>
    <td>
      <xsl:value-of select="."/>
    </td>
  </tr>
</xsl:template>

<xsl:template match="group/role[1]/Function[1]" mode="group">
  <th rowspan="{../../@size}">
    <xsl:value-of select="../../@name"/>
  </th>
</xsl:template>

<xsl:template match="group/role[position() gt 1]/Function |
                     group/role[1]/Function[position() gt 1]" mode="group"/>

<xsl:template match="group/role/Function[1]" mode="role">
  <th rowspan="{../@size}">
    <xsl:value-of select="../@name"/>
  </th>
</xsl:template>

<xsl:template match="group/role/Function[position() gt 1]" mode="role"/>

</xsl:stylesheet>

to transform an input document like

<Groups>
   <Group>
    <GroupName>GroupA</GroupName>
    <Role>
        <RoleName>Correspondence Team B</RoleName>
        <Functions>
            <Function>CT2 Work</Function>
            <Function>HOL01_My Work</Function>
            <Function>HOL02_My Work</Function>
        </Functions>
    </Role>
</Group>

<Group>
 <GroupName>GroupB</GroupName>
    <Role>
        <RoleName>Customer Service Rep</RoleName>
        <Functions>
            <Function>CSR Work</Function>
            <Function>HOL01_My Work</Function>
        </Functions>
    </Role>
</Group>
<Group>
    <GroupName>GroupB</GroupName>
    <Role>
        <RoleName>Dispute Advisor</RoleName>
        <Functions>
            <Function>DA Work</Function>
            <Function>HOL01_My Work</Function>
        </Functions>
    </Role>
</Group>
<Group>
    <GroupName>GroupA</GroupName>
    <Role>
        <RoleName>Correspondence Team</RoleName>
        <Functions>
            <Function>CT Work</Function>
            <Function>HOL01_My Work</Function>
        </Functions>
    </Role>
</Group>

<Group>
    <GroupName>GroupB</GroupName>
    <Role>
        <RoleName>Correspondence Team B</RoleName>
        <Functions>
            <Function>CT2 Work</Function>
            <Function>HOL01_My Work</Function>
            <Function>HOL02_My Work</Function>
        </Functions>
    </Role>
</Group>
</Groups>

into HTML5 like

<!DOCTYPE HTML>
<html lang="en">
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <title>Test</title>
   </head>
   <body>
      <h1>Test</h1>
      <table frame="border" rules="all">
         <thead>
            <th>Group Name</th>
            <th>Role Name</th>
            <th>Function Names</th>
         </thead>
         <tbody>
            <tr>
               <th rowspan="5">GroupA</th>
               <th rowspan="3">Correspondence Team B</th>
               <td>CT2 Work</td>
            </tr>
            <tr>
               <td>HOL01_My Work</td>
            </tr>
            <tr>
               <td>HOL02_My Work</td>
            </tr>
            <tr>
               <th rowspan="2">Correspondence Team</th>
               <td>CT Work</td>
            </tr>
            <tr>
               <td>HOL01_My Work</td>
            </tr>
            <tr>
               <th rowspan="7">GroupB</th>
               <th rowspan="2">Customer Service Rep</th>
               <td>CSR Work</td>
            </tr>
            <tr>
               <td>HOL01_My Work</td>
            </tr>
            <tr>
               <th rowspan="2">Dispute Advisor</th>
               <td>DA Work</td>
            </tr>
            <tr>
               <td>HOL01_My Work</td>
            </tr>
            <tr>
               <th rowspan="3">Correspondence Team B</th>
               <td>CT2 Work</td>
            </tr>
            <tr>
               <td>HOL01_My Work</td>
            </tr>
            <tr>
               <td>HOL02_My Work</td>
            </tr>
         </tbody>
      </table>
   </body>
</html>
Sign up to request clarification or add additional context in comments.

4 Comments

Thank you Guys for your reply. This is great Martin. I tried your code. At first, it throws error as... "net.sf.saxon.trans.XPathException:Unsupported HTML version: 5.0"... I just removed the specification of the HTML version in the xsl:output element from your code and it works. I learned that this error occurs only in Saxon9 but not in previous versions. Thank you so much.
I tested that stylesheet with Saxon 9.4 HE Java without getting any error so I am astonished that you say you get that error. But you are right, the HTML version is not needed for the stylesheet to output HTML.
I am using SaxonHE 9.4.0.6 to be exact and I am getting that error. So its not occuring in all Saxon 9. Thanks for the added info.
@MartinHonnen: Can you please take a look at stackoverflow.com/questions/30662205/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.