limit number of characters in a string - XSLT - asp.net

I am using a third party asp.net control to pull and display the latest content from the database. The control pulls the title of the latest published content using a xsl file. My issue is the title(content piece) being too long. They place I used to display has no room for about 100 characters. I need to trim(not the white spaces) end part and may be limit it to a few words or some characters. It uses the xsl file -
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<xsl:for-each select="Collection/Content">
<tr>
<td>
<a>
<xsl:attribute name="href">
<xsl:choose>
<xsl:when test="Type ='Assets' or Type = 8 ">
javascript:void window.open('showcontent.aspx?id=<xsl:value-of select="ID"/>')
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="QuickLink"/>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xsl:value-of select="Title"/>
</a>
</td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
This part, <xsl:value-of select="Title"/> is where you the title is and I need to shorten it.. (putting ... in the end perhaps)
How can I do it? Can I get this done in the xsl file itself without using JQuery? Many thanks,

<xsl:choose>
<xsl:when test="string-length(Title) > 100">
<xsl:value-of select="substring(Title, 1, 97)" />...
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="Title" />
</xsl:otherwise>
</xsl:choose>

You can use the substring(text, startingIndex, length) XSLT function:
<xsl:value-of select="substring(Title, 1, 100)"/>
Note that substring index starts from 1, instead of the usual 0.
More at http://zvon.org/xxl/XSLTreference/Output/xpathFunctionIndex.html
Note also, that .NET does not implements XSLT 2.0, only XSLT 1.0 (hence the above reference: its the list of XSLT 1.0 functions).

Limit the 20 characters
If your code likes this
<xsl:value-of select="EmpBio" disable-output-escaping="yes"/>
Just change with new one written below
<xsl:value-of select="substring(BioData, 1, 20)" disable-output-escaping="yes"/>
Note that the quotation marks are removed from the element name BioData

Related

DDR Treeview Menu display selected root and its child node

I'm working on a DDR Treeview menu for DotNetNuke to display only the selected Root items and its child node to be expanded. Here is what I'm trying to achieve.
(Left vertical menu)
Any advice please?
This is the xslt code and is currently displaying all root items.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:param name="ControlID" />
<xsl:param name="Options" />
<xsl:template match="/*">
<xsl:apply-templates select="root" />
</xsl:template>
<xsl:template match="root">
<xsl:if test="node">
<ul class="treeview filetree" id="{$ControlID}">
<xsl:apply-templates select="node" />
</ul>
<script type="text/javascript">
jQuery(function($) {
$("#<xsl:value-of select="$ControlID" />").treeview(
<xsl:value-of select="$Options" disable-output-escaping="yes" />
);
});
</script>
</xsl:if>
</xsl:template>
<xsl:template match="node">
<li>
<xsl:if test="node and (#depth != 0 or #breadcrumb = 1)">
<xsl:attribute name="class">open</xsl:attribute>
</xsl:if>
<xsl:choose>
<xsl:when test="#enabled = 0">
<xsl:value-of select="#text" />
</xsl:when>
<xsl:otherwise>
<a href="{#url}">
<xsl:choose>
<xsl:when test="#selected=1">
<xsl:attribute name="class">selected breadcrumb</xsl:attribute>
</xsl:when>
<xsl:when test="#breadcrumb=1">
<xsl:attribute name="class">breadcrumb</xsl:attribute>
</xsl:when>
</xsl:choose>
<xsl:value-of select="#text" />
</a>
</xsl:otherwise>
</xsl:choose>
<xsl:if test="node">
<ul style="list-item-style:none">
<xsl:apply-templates select="node" />
</ul>
</xsl:if>
</li>
</xsl:template>
</xsl:stylesheet>
It would help if you supplied an example of the input code you would like to transform.
I assume its basically something like this:
<root>
<node enabled="1" depth="1" text="Service" selected="true" breadcrumb="0"/>
<node>
<node>
<node/>
</node>
</node>
<node>
<node/>
</node>
<node/>
</root>
You can skip the first template-match and those first if-element and directly match only what you're interested in. Without testing, something like this should do the trick:
<!-- ... -->
<!-- process only "root" elements that have at least one "node" element -->
<xsl:template match="/root[node]">
<ul class="treeview filetree" id="{$ControlID}">
<xsl:apply-templates select="node" />
</ul>
<!-- ... -->
</xsl:template>
<xsl:template match="node">
<!-- ... -->
</xsl:template>
Without the source XML it's really hard to work out what you're trying to do here, but I'd say the main reason you're getting all nodes is the the template to match the node element is recursive and does not hide the descendants. If you add display:none to the style attribute on the ul element at the end of the node template (or change list-item-style to display), you may get what you want.
If you're only getting root items, you'll want to change the NodeSelector defined for the menu. I believe that the shorthand value RootChildren will give you what you want.

repeatedly add/append classes to output element

I've basically got an XML input structure like this:
...
<box type="rectangle" class="someOriginalClass">
<background bgtype="solid" />
<animation order="3" />
... children
</box>
and would like to transform it to
<div class="someOriginalClass rectangle solid animated order3">
...children
</div>
Note that neither background nor animation need to be there, and this is a reduced example, meaning that there could be more properties like these, with more attributes.
As well, animation and background are reused elsewhere.
My XSLT code so far is:
<xsl:template match="box">
<div class="{#someOldClass} {#type}">
<xsl:apply-templates select="./*" />
</div>
</xsl:template>
<xsl:template match="background">
<xsl:attribute name="class">
<xsl:value-of select="#bgtype"/>
</xsl:attribute>
</xsl:template>
<xsl:template match="animation">
<xsl:attribute name="class">
animated order<xsl:value-of select="#order"/>
</xsl:attribute>
</xsl:template>
The problem with this code is that each template overrides the class attribute completely, dismissing already contained classes.
To solve this, I've tried:
a) rewriting old classes => value-of only gets input XML class (someOldClass)
<xsl:template match="animation">
<xsl:attribute name="class">
<xsl:value-of select="../#class"/>
animated order<xsl:value-of select="#order"/>
</xsl:attribute>
</xsl:template>
b) instead passing changes between templates with params => only one time, one way
<xsl:template match="box">
<div class="{#someOldClass} {#type}">
<xsl:apply-templates select="./*">
<xsl:with-param name="class" select="concat(#someOldClass,' ',#type)"/>
</xml:apply-templates>
</div>
</xsl:template>
<xsl:template match="animation">
<xsl:param name="class"/>
<xsl:attribute name="class">
<xsl:value-of select="$class"/>
animated order<xsl:value-of select="#order"/>
</xsl:attribute>
</xsl:template>
You see, I'm lacking a solution that will work with any number of class updates, with minimal redundancy.
BTW, I'm an XSLT beginner, so maybe there's some predestined feature that I've simply not yet come across.
Any ideas?
I've used this before. I'm not sure what your XML looks like but this may help get you on the right path.
<xsl:template match="box">
<xsl:param name="boxType" />
<li>
<xsl:variable name="boxClass">
<xsl:value-of select="$boxType"/>
<xsl:if test="#class1 = 1"> class1</xsl:if>
<xsl:if test="#class2 = 1"> class2</xsl:if>
<xsl:if test="#class3 = 1"> class3</xsl:if>
<xsl:if test="#class4 = 1"> class4</xsl:if>
<xsl:if test="#last = 1"> lnLast</xsl:if>
</xsl:variable>
<xsl:attribute name="class">
<xsl:value-of select="$boxClass"/>
</xsl:attribute>
</li>
</xsl:template>

xsl inside for-each use different css class

how can I display the text inside a for-each loop, in xslt, using each time a different css class? can I generate somehow the name of the css class based on some variable or something?? is it possible?
for example in the following code inside the foreach loop can I display the li with a different css class each time...such as in the first iteration li class="1"...second iteartion li class="2"...and obvious in css exists li.1{..}, li.2{...}
<xsl:output method="text" indent="no"/>
<xsl:variable name="newline">
<xsl:text>
</xsl:text>
</xsl:variable>
<xsl:template match="/">
<xsl:text>Collections of books</xsl:text>
<xsl:value-of select="$newline"/>
<xsl:variable name="index" select="0"/>
<xsl:for-each select="collection/book">
<xsl:sort select="category"/>
<xsl:variable name="lastCat" select="category"/>
<xsl:if test="not(preceding-sibling::book[category=$lastCat])">
<xsl:value-of select="$newline"/>
<xsl:value-of select="category"/>
<xsl:value-of select="$newline"/>
<xsl:value-of select="$newline"/>
</xsl:if>
<ul>
<li>
<xsl:value-of select="title"/>
<xsl:text> </xsl:text>
<xsl:value-of select="author"/>
<xsl:text> </xsl:text>
<xsl:value-of select="year"/>
<xsl:text> </xsl:text>
<xsl:value-of select="isbn"/>
</li>
</ul>
<xsl:value-of select="$newline"/>
</xsl:for-each>
</xsl:template>
You're XSLT is a little confusing as to whether you are outputting text or html. However, in answer to your immediate question you can easily add attributes to the exist li elements you are outputing in one of two ways.
Firstly, you can make use of the xsl:attribute statement, which should be added immediately following the li tag.
<li>
<xsl:attribute name="class">
<xsl:value-of select="position()" />
</xsl:attribute>
...
The better method though is to use 'attribute value templates' to specify attributes. (The curly brackets indicate an AVT to be evaluated in this case, as opposed to being a piece of text to be literally output)
<li class="{position()}">
...
In both cases the output will be similar to the following
<li class="1">...
<li class="2">...
In this example I am simply using the position() to demonstrate how you can set attributes, but you could easily use variables if required.
<li class="{$classname}">

Trim first 10 characters off the title of RSS feed

I'm trying to write some xsl to style an RSS feed. I need to trim the first 10 characters off the title of each item.
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/rss">
<ul>
<xsl:for-each select="channel/item">
<li><strong><xsl:value-of select="title"/>
</strong>
More</li>
</xsl:for-each>
</ul>
</xsl:template>
<xsl:template name="trimtitle">
<xsl:param name="string" select="." />
<xsl:if test="$string">
<xsl:text>Foo</xsl:text>
<xsl:call-template name="trimtitle">
<xsl:with-param name="string" select="substring($string, 10)" />
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template match="title">
<xsl:call-template name="title" />
<xsl:value-of select="." />
</xsl:template>
</xsl:stylesheet>
I think you should write your substring function as this:
substring($string,1, 10)
Look at here
http://www.zvon.org/xxl/XSLTreference/Output/function_substring.html
What are you doing in your trimtitle template?
Why are you calling trimtitle recursive..?
The easiest way to show a trimmed string is with:
<xsl:value-of select="substring(title,0,10)"/>

How to reverse date format in XSLT?

I’m working on a site In that site some pages gets data from XML through XSLT. But the date is displayed as YYYY-MM-DD which ideally is taken from the XML which was in this format. I would like to convert this format to DD-MM-YYYY through XSLT or some other possible way.
Please suggest me an idea to go ahead or provide me the code to achieve this ASAP.
This is the format of xml giving
<published date="2009-09-28T07:06:00 CET" />
and i want to convert this into
<published date="28-09-2009T07:06:00 CET" />
and this is xsl file
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<table class="bdr-bot" width="100%" border="0" cellspacing="0" cellpadding="0" style="clear:both">
<tr>
<th width="15%" class="bdr">Date</th>
<th class="bdr">Title</th>
</tr>
<xsl:for-each select="hexML/body/press_releases/press_release">
<xsl:if test="contains(published/#date, '2009')">
<tr>
<td valign="top">
<xsl:value-of select="substring-before(published/#date, 'T')"/>
</td>
<td valign="top">
<xsl:value-of select="headline"/>
</td>
</tr>
</xsl:if>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
Now tell me the solution? is this possible with fn:reverse?
If the XML is in the format YYYY-MM-DD, you should be able to use Xpath's tokenize function to split up your string where - occurs, and then reorder it. Something akin to:
<xsl:variable name="dt" value="tokenize(Date, '-')"/>
<xsl:value-of select="concat(dt[3],'-',dt[2],'-',dt[1])"/>
This is just off the top of my head (and untested), but you get the general idea. You should be able to split up the date and reorder the pieces.
Assuming
<xml>
<date>2009-11-18</date>
</xml>
This XSLT 1.0 solution would do it:
<xsl:template match="date">
<xsl:copy>
<xsl:value-of select="
concat(
substring(., 9, 2),
'-',
substring(., 6, 2),
'-',
substring(., 1, 4)
)
" />
</xsl:copy>
</xsl:template>
If your date can be
<xml>
<date>2009-11-1</date>
</xml>
you would have to use the slightly more complicated
<xsl:template match="date">
<xsl:copy>
<xsl:value-of select="
concat(
substring-after(substring-after(., '-'), '-'),
'-',
substring-before(substring-after(., '-'), '-'),
'-',
substring-before(., '-')
)
" />
</xsl:copy>
</xsl:template>
you could also use a template.
<?xml version="1.0" encoding="utf-8"?>
<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:template match="/">
<html>
<body>
<table class="bdr-bot" width="100%" border="0" cellspacing="0" cellpadding="0" style="clear:both">
<tr>
<th width="15%" class="bdr">Date</th>
<th class="bdr">Title</th>
</tr>
<!-- <xsl:for-each select="hexML/body/press_releases/press_release">-->
<xsl:if test="contains(published/#date, '2009')">
<tr>
<td valign="top">
<xsl:call-template name="FormatDate">
<xsl:with-param name="DateTime" select="published/#date"/>
</xsl:call-template>
</td>
<td valign="top">
<a href="result-page.aspx?ResultPageURL={location/#href}">
<xsl:value-of select="headline"/>
</a>
</td>
</tr>
</xsl:if>
<!--</xsl:for-each>-->
</table>
</body>
</html>
</xsl:template>
<xsl:template name="FormatDate">
<xsl:param name="DateTime"/>
<xsl:value-of select="substring($DateTime,9,2)"/>-<xsl:value-of select="substring($DateTime,6,2)"/>-<xsl:value-of select="substring($DateTime,1,4)"/><xsl:text> CET</xsl:text>
</xsl:template>
</xsl:stylesheet>
It appears that you need to use an XSLT 2.0 schema aware processor to get built-in support for what you want to do with the xs:dateTime data type and the format-date function.
See http://www.w3.org/TR/xmlschema-2/#dateTime for the requirements for XSLT 2.0 being able to parse the string you have.
The ·lexical space· of dateTime
consists of finite-length sequences of
characters of the form: '-'? yyyy '-'
mm '-' dd 'T' hh ':' mm ':' ss ('.'
s+)? (zzzzzz)?
See http://www.dpawson.co.uk/xsl/rev2/dates.html#d16685e16 for generating output.
format-date( xs:date(
concat(
substring($d,1,4),
'-',
substring($d,7,2),
'-',
substring($d,5,2))),
'[D01] [MNn] [Y0001]')

Resources