Reputation: 77
I am very new to XML and XSLT but I am trying to create a HTML page that loops through a varying length of steps and produces a list in HTML.
The XML looks something like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<module>
<name ID="SDCModule002">
<role>SDC</role>
<modNum>002</modNum>
<title>Test</title>
<audience>me</audience>
<numSteps>7</numSteps>
<steps>
<step1>Do this 1</step1>
<step2>Do this 2</step2>
<step3>Do this 3</step3>
<step4>Do this 4</step4>
<step5>Do this 5</step5>
<step6>Do this 6</step6>
<step7>Do this 7</step7>
</steps>
</name>
<name ID="SDCModule003">
<role>SDC</role>
<modNum>003</modNum>
<title>Hi</title>
<audience>you</audience>
<numSteps>4</numSteps>
<steps>
<step1>Hi</step1>
<step2>There</step2>
<step3>You</step3>
<step4>Guys</step4>
</steps>
</name>
</module>
</xml>
I have it so the information like Title, audience, task etc. are displayed for the module I am searching so that works.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/xml">
<html>
<head>
<title><xsl:value-of select="module/name[@ID='SDCModule001']/title "/></title>
</head>
<xsl:apply-templates select="module/name[@ID='SDCModule001']"/>
</body>
</html>
</xsl:template>
<xsl:template name="stepList" match="name">
<div id= "info">
<center>
<font face="verdana" size="2"><b><center><xsl:value-of select="title" /></center></b></font>
<hr></hr>
<xsl:value-of select="audience" />
<p></p>
<xsl:value-of select="numSteps" />
</center>
</div>
</xsl:template>
</xsl:stylesheet>
I think I need to have a <xsl:for-each>
that lists the steps in an ordered list, so SDCModule002 will have 7 steps, and SDCModule003 will only have 4, or do I just get the values of all child nodes of the parent <steps>
?
I don't want to do 15 if statements saying "if numSteps is 1, then do this.... if numSteps is 2, then do that" etc... I can and it would work but I am not sure if there is a more efficient way of doing this.
Edited
The expected results would be like this:
Module: SCDModule001 Title: Test Audience: Me Steps: 1. Do this 1 2. Do this 2 3. Do this 3 4. Do this 4 6. Do this 5 7. Do this 6 8. Do this 7
Upvotes: 0
Views: 2317
Reputation: 11
As a rule of thumb you should avoid the use of xsl:for-each when it's not needed. Although it does not really matter, performance wise, for small translations or projects. The added benefit of apply-templates is that you only have to change the xpaths if the input is changed during realisation.
Here's an example which creates 2 html files per module. The template what matches "steps" is an extra, you don't need it to make it work.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/xml">
<xsl:apply-templates select="module/name"/>
</xsl:template>
<!--Each name is a file - but can easily changed to module -->
<xsl:template match="name">
<html>
<head>
<title>***<xsl:value-of select="@ID"/>***</title>
</head>
<body>
<div id= "info">
<center>
<font face="verdana" size="2">
<b>
<center>
<xsl:value-of select="title" />
</center>
</b>
</font>
<hr />
<xsl:value-of select="audience" />
<p></p>
<xsl:apply-templates select="steps"/>
</center>
</div>
</body>
</html>
</xsl:template>
<!--Extra match for styling - steps can also directly be called from "name" template-->
<xsl:template match="steps">
<xsl:value-of select="numSteps" />
<ol>
<xsl:apply-templates select="node()" mode="steps"/>
</ol>
</xsl:template>
<!--Wildcard - matches all step nodes-->
<xsl:template match="*" mode="steps">
<li><xsl:value-of select="." /></li>
</xsl:template>
Upvotes: 1
Reputation: 29052
Incorporating an xsl:for-each
above the step?
elements could look like the following. I also changed some the xsl:apply-templates
to show all module/name
s in the output. The output is not pretty, but should give you a good start. Don't forget to add an
<?xml-stylesheet href="test.xslt" type="text/xsl" ?>
line to your XML to run it in the browser.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="text()" />
<xsl:template match="/xml">
<html>
<head>
<title>***<xsl:value-of select="module/name[@ID='SDCModule002']/title "/>***</title>
</head>
<body>
<xsl:apply-templates select="module/name"/>
</body>
</html>
</xsl:template>
<xsl:template match="steps">
<div id= "info">
<center>
<font face="verdana" size="2">
<b>
<center>
<xsl:value-of select="../title" />
</center>
</b>
</font>
<hr />
<xsl:value-of select="../audience" />
<p></p>
<xsl:value-of select="../numSteps" />
<ol>
<xsl:for-each select="*">
<li><xsl:value-of select="." /></li>
</xsl:for-each>
</ol>
</center>
</div>
</xsl:template>
</xsl:stylesheet>
In Firefox, the output looks like this:
Upvotes: 1