get last item in content query web part using xslt (SharePoint 2010) - xslt

This is my first time that I am using Content Query Web part and xslt. I have to display the last 5 posts from a blog in the following fashion (please look at the image below):
The table contains two columns. In the left column I would like to display the last post and in the right column I would like to display the rest of the posts from a particual blog.
Edit 1
The source is just an OOTB Blog Site and I have added a few posts in it. I would like to display these posts in an html table which contains two columns. In the left column I would like to display the last post entered in the blog and in the right column I would like to loop through other posts. The user must specify how many posts he/she would like to see in the CQWP.
Edit 2
This is the xslt that I have created so far. The only think is that the table is being repeated multiple times, which I don't want that. There should be only one table. If you look in the xslt code I have manually entered some text, like Test1, test 2... In their place I would like to display the rest of the blog posts.
<xsl:template name="Post" match="Row[#Style='Post']" mode="itemstyle">
<xsl:variable name="SafeLinkUrl">
<xsl:call-template name="OuterTemplate.GetSafeLink">
<xsl:with-param name="UrlColumnName" select="'LinkUrl'"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="DisplayTitle">
<xsl:call-template name="OuterTemplate.GetTitle">
<xsl:with-param name="Title" select="#Title"/>
<xsl:with-param name="UrlColumnName" select="'LinkUrl'"/>
</xsl:call-template>
</xsl:variable>
<div>
<table width="100%" cellpadding="2" cellspacing="2" border="1">
<tr>
<td colspan="2" valign="top">
<xsl:value-of select="#Author"/></td>
<td rowspan="2" valign="top" width="30%">
<div>
<b>Previous blog posts:</b>
</div>
<div>
<ul style="margin-left:-2px;">
<li>Test 1</li>
<li>Test 2</li>
<li>Test 3</li>
<li>Test 4</li>
</ul>
</div>
</td>
</tr>
<tr>
<td width="15%" valign="top">
image</td>
<td valign="top">
<div>
<xsl:value-of select="#Title"/>
</div>
<div class="custom_description">
<xsl:value-of select="#Body" disable-output-escaping="yes" />
</div>
<p>
<xsl:call-template name="OuterTemplate.CallPresenceStatusIconTemplate"/>
<a href="{$SafeLinkUrl}">
<xsl:if test="$ItemsHaveStreams = 'True'">
<xsl:attribute name="onclick">
<xsl:value-of select="#OnClickForWebRendering"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="$ItemsHaveStreams != 'True' and #OpenInNewWindow = 'True'">
<xsl:attribute name="onclick">
<xsl:value-of disable-output-escaping="yes" select="$OnClickTargetAttribute"/>
</xsl:attribute>
</xsl:if>
<br />
<b>Read More ></b>
</a>
</p>
</td>
</tr>
</table>
</div>
</xsl:template>
Edit 3
<root>
<Posts>
<Post ID="1">
<Title>this post 1</Title>
<Body>The comment comes here</Body>
</Post>
<Post ID="2">
<Title>this post 2</Title>
<Body>The comment comes here</Body>
</Post>
<Post ID="3">
<Title>this post 3</Title>
<Body>The comment comes here</Body>
</Post>
<Post ID="4">
<Title>this post 4</Title>
<Body>The comment comes here</Body>
</Post>
<Post ID="5">
<Title>this post 5</Title>
<Body>The comment comes here</Body>
</Post>
</Posts>
</root>
Thank you

First let me caveat emptor: I know nothing about SharePoint, and I do not have an installation of SharePoint installed. There is a StackExchange website which specialised in SharePoint questions, and this site may serve you better than SO. See https://sharepoint.stackexchange.com/questions/22465/recreating-the-blog-template
You should also take a look at http://www.glynblogs.com/2011/04/overriding-the-presentation-of-an-xslt-list-view-web-part.html .
UPDATE
This XSLT 1.0 style-sheet, for an MS XSLT processor...
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="xsl msxsl">
<xsl:output method="html" doctype-system="" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*" />
<xsl:variable name="empty-main">
<empty-main>No content yet.</empty-main>
</xsl:variable>
<xsl:variable name="empty-sub">
<empty-main>No older content yet.</empty-main>
</xsl:variable>
<xsl:template match="/*">
<html>
<head>
<title>Blog</title>
<style type="text/css">
table {
width: 100%;
border: 1px solid #000;
}
td.main-col, td.subsiduary-col {
vertical-align:text-top;
}
td.main-col {
width: 75%
}
td.subsiduary-col {
width: 25%
}
</style>
</head>
<body>
<table border="1">
<tr>
<xsl:variable name="count-posts" select="count(msxsl:node-set(Posts/Post))" />
<td class="main-col">
<xsl:apply-templates select="
(Posts/Post[last()] | msxsl:node-set($empty-main))[1]" />
</td>
<td class="subsiduary-col">
<xsl:apply-templates select="
Posts/Post[position() > last() - 5 and position() < last()] |
msxsl:node-set($empty-sub)[$count-posts < 2]" />
</td>
</tr>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="Post">
<xsl:apply-templates select="Title" />
<p><xsl:copy-of select="Body/node()" /></p>
</xsl:template>
<xsl:template match="Post[last()]/Title" priority="2">
<h1><xsl:value-of select="." /></h1>
</xsl:template>
<xsl:template match="Post/Title">
<h2><xsl:value-of select="." /></h2>
</xsl:template>
<xsl:template match="empty-main|empty-sub" priority="2">
<p><xsl:value-of select="." /></p>
</xsl:template>
</xsl:stylesheet>
...will transform this input...
<root>
<Posts>
<Post ID="1">
<Title>this post 1</Title>
<Body>The comment comes here</Body>
</Post>
<Post ID="2">
<Title>this post 2</Title>
<Body>The comment comes here</Body>
</Post>
<Post ID="3">
<Title>this post 3</Title>
<Body>The comment comes here</Body>
</Post>
<Post ID="4">
<Title>this post 4</Title>
<Body>The comment comes here</Body>
</Post>
<Post ID="5">
<Title>this post 5</Title>
<Body>The comment comes here</Body>
</Post>
</Posts>
</root>
..into this output...
<!DOCTYPE html SYSTEM "">
<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Blog</title>
<style type="text/css">
table {
width: 100%;
border: 1px solid #000;
}
td.main-col, td.subsiduary-col {
vertical-align:text-top;
}
td.main-col {
width: 75%
}
td.subsiduary-col {
width: 25%
}
</style>
</head>
<body>
<table border="1">
<tr>
<td class="main-col">
<h1>this post 5</h1>
<p>The comment comes here</p>
</td>
<td class="subsiduary-col">
<h2>this post 1</h2>
<p>The comment comes here</p>
<h2>this post 2</h2>
<p>The comment comes here</p>
<h2>this post 3</h2>
<p>The comment comes here</p>
<h2>this post 4</h2>
<p>The comment comes here</p>
</td>
</tr>
</table>
</body>
</html>
For a visual of how this renders in a browser, paste the html output into http://htmledit.squarefree.com/ .

Displays the first or the last item depending on Sorting selected in the panel tool of the web part.
<xsl:if test="count(preceding-sibling::*)=0">
Example
<xsl:template name="DisplayPosts" match="Row[#Style='DisplayPosts']" mode="itemstyle">
<table width="100%" border="1">
<tr>
<td width="70%">
<xsl:if test="count(preceding-sibling::*)=0">
<xsl:value-of select="#Title" />
</xsl:if>
</td>
<td width="30%">
<xsl:if test="count(preceding-sibling::*)>0">
<xsl:value-of select="#Title" />
</xsl:if>
</td>
</tr>
</table>
</xsl:template>

Related

How to Enumerate a Table Sequentially

I would like to know how it is possible to enumerate a table sequentially and to save this value into some kind of variable so this value can be selected in another template.
Each time the template table is called, the variable has to be incremented (the first value of the "counter" has to be 1).
<xsl:output method="html"/>
<xsl:template match="/">
<html>
<head>
<title>Tables.</title>
</head>
<body>
<xsl:apply-templates select="table"/>
<!-- apply more templates -->
</body>
</html>
</xsl:template>
<xsl:template match="table">
<center>
<b>Table **ENUMERATION OF THE TABLE** - </b><xsl:value-of select="title"/>
</center>
<br/>
</xsl:template>
<!-- more templates -->
Input (XML):
<table id="table1">
<title>Title.</title>
<br/>
</table>
<table id="table2">
<title>Title.</title>
<br/>
</table>
Output (HTML):
Table 1 - Title.
Table 2 - Title.
Your example is not a good one. If your input looks something like:
<root>
<table id="table1">
<title>Title 1</title>
</table>
<not-table/>
<table id="table2">
<title>Title 2</title>
</table>
<not-table/>
<table id="table3">
<title>Title 3</title>
</table>
</root>
then applying:
<xsl:template match="/root">
<xsl:copy>
<xsl:apply-templates select="table"/>
</xsl:copy>
</xsl:template>
<xsl:template match="table">
<center>
<b>Table <xsl:value-of select="position()"/> - </b>
<xsl:value-of select="title"/>
</center>
<br/>
</xsl:template>
will result in:
<root>
<center>
<b>Table 1 - </b>Title 1</center>
<br/>
<center>
<b>Table 2 - </b>Title 2</center>
<br/>
<center>
<b>Table 3 - </b>Title 3</center>
<br/>
</root>

xsl 1.0 Why won't a node match return data

I'm using the following xml information:
<section>
<...>
</section>
<section>
<templateId root="2.16.840.1.113883.10.20.22.2.10" />
<text>
<table id="Appointments">
<tr>
<td id="heading">Appointments</td>
</tr>
<tr>
<td id="content">No future appointments scheduled.</td>
</tr>
</table>
<br />
<table id="Referrals">
<tr>
<td id="heading">Referrals</td>
</tr>
<tr>
<td id="content">No referrals available.</td>
</tr>
</table>
<br />
</text>
<section>
<section>
<...>
</section>
There are multiple section nodes (with their own child nodes, including templateId) within the document. I'm having trouble with this one so I wanted to be specific in the xml information.
and in my xslt file I want to get one particular table out. I'm referencing it the following way (I'm trying to use templates and I'm new to XSL so please bear with me)
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ms="urn:schemas-microsoft-com:xslt"
xmlns="http://www.w3.org/1999/xhtml">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/">
<xsl:apply-templates select="//section[templateId/#root='2.16.840.1.113883.10.20.22.2.17']/text/table[#id='Appointments']" />
</xsl: template>
<xsl:template match="section[templateId/#root='2.16.840.1.113883.10.20.22.2.17']/text/table[#id='Appointments']">
<div style="float: left; width: 50%;">
<span style="font-weight: bold;">
<xsl:value-of select="tr/td[#id='heading']"/>:
</span>
<br />
<xsl:call-template name="replace">
<xsl:with-param name="string" select="tr/td[#id='content']"/>
</xsl:call-template>
</div>
</xsl:template>
<xsl:template name="replace">
<xsl:param name="string"/>
<xsl:choose>
<xsl:when test="contains($string,'
')">
<xsl:value-of select="substring-before($string,'
')"/>
<br/>
<xsl:call-template name="replace">
<xsl:with-param name="string" select="substring-after($string,'
')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$string"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
In this particular xml example, the output should be:
Appointments:
No future appointments scheduled.
I'm thinking the match and select need some tweaking but not sure what part.
Also, if the template can be tweaked so that I could pass a parameter with the table/#id value so that I could reuse this one template for a couple of items,that would be even more beneficial (the output for referrals and appointments that are in this example would be the same).
Thanks for any help
This is your XML section root attribute (cut and paste from your XML):
root="2.16.840.1.113883.10.20.22.2.10"
This is your test XSL:
root='2.16.840.1.113883.10.20.22.2.17'
Of course they do not match, one ends with "10", the other with "17"
Changing the data to "17" and correcting the other errors in my comments yields:
<div style="float: left; width: 50%;"><span style="font-weight: bold;">Appointments:
</span><br>No future appointments scheduled.
</div

XSLT following-sibling not returning values

I am trying to create a standings board for a soccer league. I am very new to XSLT and blundering my way around.
Below is the data format that I have
Data:
<sports-statistics>
<sports-team-stats>
<date year="2013" month="4" date="23" day="2"/>
<time hour="16" minute="00" second="59" timezone="Eastern" utc-hour="-4" utc-minute="00"/>
<version number="2"/>
<league global-id="513" name="Youth Soccer League" alias="YSL" display-name=""/>
<season year="2013" id="1" description="2013 YSL Season"/>
<soccer-ifb-team-stats>
<ifb-team>
<team-info global-id="11270" id="1869" location="Tulsa" name="Astecs" alias="TUL" display-name="Astecs"/>
<split id="0" type="all" name="All Games">
<games-played games="1"/>
<record wins="0" losses="0" ties="1" percentage=".500"/>
<minutes minutes="90"/>
<goals goals="1" headed="0" kicked="1" />
<opponent-goals goals="1"/>
<own-goals goals="0"/>
<assists assists="1"/>
<opponent-assists assists="1"/>
<shots shots="18"/>
<opponent-shots shots="10"/>
<shots-on-goal shots="7"/>
<opponent-shots-on-goal shots="4"/>
</split>
<split id="302" type="home" name="Home Games">
<games-played games="1"/>
<record wins="0" losses="0" ties="1" percentage=".500"/>
<minutes minutes="90"/>
<goals goals="1" headed="0" kicked="1" />
<opponent-goals goals="1"/>
<own-goals goals="0"/>
<assists assists="1"/>
<opponent-assists assists="1"/>
<shots shots="18"/>
<opponent-shots shots="10"/>
<shots-on-goal shots="7"/>
<opponent-shots-on-goal shots="4"/>
</split>
</ifb-team>
</soccer-ifb-team-stats>
</sports-team-stats>
</sports-statistics>
Here is my code so far.
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
<xsl:output method="html" indent="yes" encoding = "utf-8" standalone = "yes"/>
<xsl:variable name="allGames">
<map gametype="All Games" />
</xsl:variable>
<xsl:variable name="gameMapping" select="msxsl:node-set($allGames)/*" />
<xsl:template match="/">
<html>
<head>
<meta charset="utf-8" />
<title> Standings</title>
</head>
<body>
<h2> TEST </h2>
<table border="1" style="width: 100%;">
<tr>
<th>Club</th>
<th>GP</th> <!--Games Played-->
<th>W</th> <!--Wins-->
<th>L</th> <!--Loss-->
<th>T</th> <!--Ties-->
<th>%</th> <!--Win Loss Ratio-->
</tr>
<xsl:apply-templates select="//ifb-team/split[#name = 'All Games']" />
</table>
</body>
</html>
</xsl:template>
<xsl:template match="ifb-team/split">
<xsl:variable name="ti" select="../team-info" />
<tr>
<td>
<xsl:value-of select="$ti/#display-name" />
</td>
<td>
<xsl:value-of select="following-sibling::games-played/#games"/>
</td>
<td>
<xsl:value-of select="following-sibling::record/#wins"/>
</td>
<td>
<xsl:value-of select="following-sibling::record/#losses"/>
</td>
<td>
<xsl:value-of select="following-sibling::record/#ties"/>
</td>
<td>
<xsl:value-of select="following-sibling::record/#percentage"/>
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
All I am getting is a table with the display name and nothing else. I am not getting any of the siblings data. What am I missing?
This is simple:
games-played is not a sibling -- it is a child of split.
The same is true for record.
Therefore, use:
<td>
<xsl:value-of select="games-played/#games"/>
</td>
<td>
<xsl:value-of select="record/#wins"/>
</td>
<td>
<xsl:value-of select="record/#losses"/>
</td>
<td>
<xsl:value-of select="record/#ties"/>
</td>
<td>
<xsl:value-of select="record/#percentage"/>
</td>

How can I produce columnar output from 2-level grouping in XML?

I have the following xml:
input
<page>
<group category="cat1">
<item fileunder="#">.45 colt</item>
<item fileunder="#">8 queens</item>
<item fileunder="#">9 lives</item>
<item fileunder="#">99 bottles of beer</item>
<item fileunder="A">An innocent man</item>
<item fileunder="A">Academy awards</item>
<item fileunder="B">Before the dawn</item>
</group>
<group category="cat2">
<item fileunder="R">Rows of houses</item>
</group>
</page>
The input items are already sorted.
desired output
I want to produce a 3-column HTML table for every group, with a subheading (a 3-column spanning cell) for each distinct fileunder, optimally presented in a top-down, then-next-column (the items are already sorted):
<table>
<tr><td colspan="3">#</td></tr>
<tr><td>.45 colt</td><td>9 lives</td><td>99 bottles of beer</td></tr>
<tr><td>8 queens</td></tr>
<tr><td colspan="3">A</td></tr>
<tr><td>An innocent man</td><td>Academy awards</td></tr>
<tr><td colspan="3">B</td></tr>
<tr><td>Before the dawn</td></tr>
</table>
<table>
<tr><td colspan="3">R</td></tr>
<tr><td>Rows of houses</td></tr>
</table>
I can live if the items are presented as left-to-right, then-next-row.
What I have so far is:
current xslt
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="itm_grp" match="/page/group/item" use="concat(../#category,':',#fileunder)"/>
<xsl:template match="page/group">
<table>
<xsl:for-each select="item[.=key('itm_grp',concat(../#category,':',#fileunder))[1]]">
<tr><td colspan="3"><xsl:value-of select="#fileunder"/></td></tr>
<xsl:variable name="nodeset" select="key('itm_grp',concat(../#category,':',#fileunder))"/>
<xsl:for-each select="$nodeset[position() mod 3=1]">
<tr>
<td><xsl:value-of select="."/></td>
<td><xsl:value-of select="following-sibling::item[1]"/></td>
<td><xsl:value-of select="following-sibling::item[2]"/></td>
</tr>
</xsl:for-each>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
which produces a left-to-right, then-next-row output (non-optimal); however, the following-sibling selects produce a “bleed-through” effect:
#
.45 colt 8 queens 9 lives
99 bottles of beer An innocent man Academy awards
A
An innocent man Academy awards Before the dawn
B
Before the dawn
R
Rows of houses
As you can see, fileunder # has two A items, and fileunder A has one B item.
So, my question is:
How can I produce the desired output (column-wise)?
If I can't do that, how can I have the row-wise output avoiding the “bleeding”?
Please note that I have very little experience with XSLT, so if my code is blatantly inefficient/idiotic/whatever, please feel free to educate me by replacing all of it!
NB: XSLT version 1, so apparently no index-of function is available.
There is a slight contradiction between your narrative and your listed expected output. You have asked for top-down, then left-right column fill order, which you have so in the listing for the non-empty values, but not for the empties. This spatial order implies that a whole column must be filled out before the next column can begin. I have assumed that your listing was a mistake and what your really want in output is ...
<table>
<tr>
<td colspan="3">#</td>
</tr>
<tr>
<td>.45 colt</td>
<td>9 lives</td>
<td>&npsp;</td>
</tr>
<tr>
<td>8 queens</td>
<td>99 bottles of beer</td>
<td>&npsp;</td>
</tr>
<tr>
<td colspan="3">A</td>
</tr>
<tr>
<td>An innocent man</td>
<td>Academy awards</td>
<td>&npsp;</td>
</tr>
<tr>
<td colspan="3">B</td>
</tr>
<tr>
<td>Before the dawn</td>
<td>&npsp;</td>
<td>&npsp;</td>
</tr>
</table>
<table>
<tr>
<td colspan="3">R</td>
</tr>
<tr>
<td>Rows of houses</td>
<td>&npsp;</td>
<td>&npsp;</td>
</tr>
</table>
... which is consistent top-down, then left-right column fill order.
This XSLT 1.0 style-sheet...
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" doctype-system="about:legacy-compat" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:key name="kItemByFile" match="item" use="concat(../#category,':',#fileunder)"/>
<xsl:template match="/">
<html lang="en">
<head><title>Songs</title></head>
<body>
<xsl:apply-templates select="*/group" />
</body>
</html>
</xsl:template>
<xsl:template match="group">
<xsl:variable name="cat" select="concat(#category,':')" />
<table>
<xsl:apply-templates select="item[
generate-id() = generate-id(key('kItemByFile',concat($cat,#fileunder))[1])]"
mode="group-head" />
</table>
</xsl:template>
<xsl:template match="item" mode="group-head">
<xsl:variable name="items"
select="key('kItemByFile',concat(../#category,':',#fileunder))" />
<xsl:variable name="row-count" select="ceiling( count($items) div 3)" />
<tr><td colspan="3"><xsl:value-of select="#fileunder" /></td></tr>
<xsl:for-each select="$items[position() <= $row-count]">
<xsl:variable name="pos" select="position()" />
<xsl:apply-templates select="." mode="row">
<xsl:with-param name="items" select="$items" />
<xsl:with-param name="row" select="$pos" />
<xsl:with-param name="row-count" select="$row-count" />
</xsl:apply-templates>
</xsl:for-each>
</xsl:template>
<xsl:template match="item" mode="row">
<xsl:param name="items" select="/.." />
<xsl:param name="row" select="1" />
<xsl:param name="row-count" select="1" />
<tr>
<xsl:apply-templates select="
$items[(position() mod $row-count) = ($row mod $row-count)]" mode="td" />
<xsl:variable name="full-cols" select="floor((count($items) div $row-count))" />
<xsl:variable name="part-col" select="number($row <
((count($items) mod $row-count) + 1))" />
<xsl:variable name="empties" select="3 - ($full-cols + $part-col)" />
<xsl:for-each select="(document('')/*/*)[position() <= $empties]">
<xsl:call-template name="empty-cell" />
</xsl:for-each>
</tr>
</xsl:template>
<xsl:template match="item" mode="td">
<td><xsl:value-of select="." /></td>
</xsl:template>
<xsl:template name="empty-cell">
<td> </td>
</xsl:template>
</xsl:stylesheet>
...when applied to this input...
<page>
<group category="cat1">
<item fileunder="#">.45 colt</item>
<item fileunder="#">8 queens</item>
<item fileunder="#">9 lives</item>
<item fileunder="#">99 bottles of beer</item>
<item fileunder="A">An innocent man</item>
<item fileunder="A">Academy awards</item>
<item fileunder="B">Before the dawn</item>
</group>
<group category="cat2">
<item fileunder="R">Rows of houses</item>
</group>
</page>
...yields...
<!DOCTYPE html SYSTEM "about:legacy-compat">
<html lang="en">
<head>
<META http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Songs</title>
</head>
<body>
<table>
<tr>
<td colspan="3">#</td>
</tr>
<tr>
<td>.45 colt</td>
<td>9 lives</td>
<td> </td>
</tr>
<tr>
<td>8 queens</td>
<td>99 bottles of beer</td>
<td> </td>
</tr>
<tr>
<td colspan="3">A</td>
</tr>
<tr>
<td>An innocent man</td>
<td>Academy awards</td>
<td> </td>
</tr>
<tr>
<td colspan="3">B</td>
</tr>
<tr>
<td>Before the dawn</td>
<td> </td>
<td> </td>
</tr>
</table>
<table>
<tr>
<td colspan="3">R</td>
</tr>
<tr>
<td>Rows of houses</td>
<td> </td>
<td> </td>
</tr>
</table>
</body>
</html>
Note
For the empty cells in the output, when viewing the lexical HTML, you will get either or the literal white space equivalent. It is XSLT processor implementation dependant, but should not cause you any concern because it is model-equivalent.
Easiest way to fix that:
<xsl:variable name="header" select="#fileunder"/>
...
<xsl:value-of select="following-sibling::item[#fileunder=$header][1]"/>
<xsl:value-of select="following-sibling::item[#fileunder=$header][2]"/>

XSLT: trying to do a contains() with a full XPath. Why does this fail?

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="utf-8" />
<xsl:template match="/">
<html>
<body>
<span>
<div style="background-color:#000066;color:#EEEEEE;padding:7px">
<a name="top" style="padding-left:10px;font-size:28pt">Alerting Variables</a>
</div>
</span>
<div style="display:block;padding-left:50px;padding-bottom:10px" class="hbuttons">
LDMS Alerts
LDSM Alerts
Why?
Examples
Resources
</div>
<div style="clear: left;"></div>
<!-- This is the Table of Contents-->
<div style="padding:5px">
<div style="padding:5px;margin-top:10pt;margin-bottom:10pt;font-weight:bold;font-size:20px">Table of Contents -
<a style="position:absolute;margin-left:40px" href="PrintPages/PrintAll.html">
<img border="0" src="images/PrintButton.png" />
</a></div>
<div style="font-family:Arial;font-weight:bold;margin-left:30px;font-size:10pt">
<xsl:if test="contains(identifiers/sectionname/alert/#name, 'Agent Watcher')">
Agent Watcher
<a style="position:absolute;margin-left:40px" href="PrintPages/PrintAW.html">
<img border="0" src="images/PrintButton.png" />
</a>
</xsl:if>
<ol style="margin-top:5">
<xsl:for-each select="identifiers/sectionname/alert">
<xsl:if test="contains(#name, 'Agent Watcher')">
<li style="margin-left:10pt;font-size:8pt">
<a>
<xsl:attribute name="href">#
<xsl:value-of select="#name" /></xsl:attribute>
<xsl:value-of select="#name" />
</a>
</li>
</xsl:if>
</xsl:for-each>
</ol>
</div>
<div style="font-family:Arial;font-weight:bold;margin-left:30px;font-size:10pt">
Intel vPro
<a style="position:absolute;margin-left:40px" href="PrintPages/PrintvPro.html">
<img border="0" src="images/PrintButton.png" />
</a>
<ol style="margin-top:5">
<xsl:for-each select="identifiers/SectionName/alert">
<xsl:if test="contains(#name, 'Intel vPro')">
<li style="margin-left:10pt;font-size:8pt">
<a>
<xsl:attribute name="href">#
<xsl:value-of select="#name" /></xsl:attribute>
<xsl:value-of select="#name" />
</a>
</li>
</xsl:if>
</xsl:for-each>
</ol>
</div>
</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Above is my code sample.
The first xsl:if statement always fails and never shows the Agent Watcher text or print me button. Even if the section is filled out in the XML. If the section is there, the first xsl:if statement fails, but the second one, contained in the xsl:for-each shows the content. How do I get this to work.
I want to have it encompassing so that if the XML has content in the section it will put it up but if not it wont be empty content with a header or vice versa. Attaching sample XML to process.
<identifiers>
<sectionname>
<alert name="Agent Watcher Service Startup"></alert>
<alert name="Agent Watcher Service Not Started"></alert>
<alert name="Agent Watcher Service Uninstalled"></alert>
<alert name="Agent Watcher File Deleted"></alert>
</sectionname>
<sectionname>
<alert name="Intel vPro agentless discovery failure"></alert>
<alert name="Intel vPro System Defense Remediation Alert"></alert>
<alert name="Intel vPro Enhanced System Defense Remediation Alert"></alert>
<alert name="Intel vPro Enhanced System Defense Alert"></alert>
</sectionname>
</identifiers>
Blockquote
I have a few other suggestions but you need to post the entire (relevant) XSLT before I can go on. At least the enclosing template is necessary.
EDIT: Here is my proposal for your stylesheet:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:tmp="http://tempuri.org"
exclude-result-prefixes="tmp"
>
<tmp:config>
<tmp:alert label="Agent Watcher" link="PrintPages/PrintAW.html" />
<tmp:alert label="Intel vPro" link="PrintPages/PrintvPro.html" />
</tmp:config>
<xsl:variable name="everyAlert" select="
/identifiers/sectionname/alert
" />
<xsl:template match="/">
<html>
<body>
<!-- 8< snip -->
<div style="...">
<div style="...">
<xsl:text>Table of Contents - </xsl:text>
<a style="..." href="PrintPages/PrintAll.html">
<img border="0" src="images/PrintButton.png" />
</a>
</div>
<xsl:for-each select="document('')/*/tmp:config/tmp:alert">
<xsl:call-template name="section" />
</xsl:for-each>
</div>
</body>
</html>
</xsl:template>
<xsl:template name="section">
<xsl:variable name="this" select="." />
<xsl:variable name="alerts" select="
$everyAlert[contains(#name, $this/#label)]
" />
<xsl:if test="$alerts">
<div style="...">
<a href="#{translate($this/#label, ' ', '_')}">
<xsl:value-of select="$this/#label" />
</a>
<a style="..." href="{$this/#link}">
<img border="0" src="images/PrintButton.png" />
</a>
<ol style="...">
<xsl:for-each select="$alerts">
<li style="...">
<xsl:value-of select="#name" />
</li>
</xsl:for-each>
</ol>
</div>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Key features:
efficient code reuse through a named template
printed sections are easily configurable
uses <xsl:text> elements to avoid unwanted whitespace in the output while retaining freedom to format the XSLT code properly
uses attribute literal notation (the curly braces {}) instead of verbose <xsl:attribute> elements
uses a temporary namespace to allow storing config data in the stylesheet itself
uses an <xsl:for-each> loop and the document() function to retrieve and work with that config data
the for-each makes use of the context to transport the current #label and #link so no <xsl:param> is necessary (the <xsl:template name="section"> runs in tmp:config/tmp:alert context, not in sectionname/alert context!)
uses a global variable ($everyAlert) to store all nodes for later use