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)"/>
Related
I'm trying to edit some XML with a transform but I'm struggling to achieve my desired results.
I have some XML:
<FX>
<Order ATTRIBUTE1="ACTIVE" ATTRIBUTE2="CCY" />
<Attribute NAME="N1" VALUE="V1" />
<Attribute NAME="N2" VALUE="V2" />
<Attribute NAME="N3" VALUE="V3" />
</FX>
And I want to transform it to look like:
<FX>
<Order ATTRIBUTE1="ACTIVE" ATTRIBUTE2="CCY" />
<Attribute NAME="N1, N2, N3" VALUE="V1,V2,V3" />
</FX>
Is this possible? Can anyone offer any suggestions on how to do this with a transform?
You can use the following, Asp.NET compatable, XSLT-1.0 stylesheet to perform an XSLT transformation from your source XML to your destination XML:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/FX">
<xsl:copy>
<xsl:copy-of select="Order" />
<Attribute>
<xsl:attribute name="NAME">
<xsl:for-each select="Attribute">
<xsl:value-of select="#NAME" />
<xsl:if test="position() != last()">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:attribute>
<xsl:attribute name="VALUE">
<xsl:for-each select="Attribute">
<xsl:value-of select="#VALUE" />
<xsl:if test="position() != last()">
<xsl:text>,</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:attribute>
</Attribute>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Its output is:
<FX>
<Order ATTRIBUTE1="ACTIVE" ATTRIBUTE2="CCY"/>
<Attribute NAME="N1, N2, N3" VALUE="V1,V2,V3"/>
</FX>
In general, if you want to transform some nodes but keep the rest you use the identity transformation template as the starting point and then add templates that change those nodes you want to change:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="FX/Attribute[1]">
<xsl:copy>
<xsl:apply-templates select="#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="FX/Attribute[position() > 1]"/>
<xsl:template match="FX/Attribute[1]/#*">
<xsl:attribute name="{name()}">
<xsl:for-each select=". | ../following-sibling::Attribute/#*[name() = name(current())]">
<xsl:if test="position() > 1">,</xsl:if>
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/jyH9rNk
I have an xml file I want to both rename the element name and return the date part of the date only to produce
<!-- reference the stylesheet -->
<?xml-stylesheet type="text/xsl" href="Dates.xsl"?>
<user>
<dob>1992-02-22T00:00:00.0000000</dob>
</user>
I want to both rename the element name and return the date part of the date only to produce
<!-- reference the stylesheet -->
<?xml-stylesheet type="text/xsl" href="Dates.xsl"?>
<user>
<USER_DOB>1992-02-22</USER_DOB>
</user>
In my XSL file
To change the element name this works
<xsl:template match="dob">
<USER_DOB><xsl:apply-templates select="node()"/></USER_DOB>
</xsl:template>
To change the date this works
<xsl:template match="dob">
<xsl:copy>
<xsl:call-template name="FormatDate">
<xsl:with-param name="DateTime" select="."/>
</xsl:call-template>
</xsl:copy>
</xsl:template>
<xsl:template name="FormatDate">
<xsl:param name="DateTime" />
<xsl:variable name="date">
<xsl:value-of select="substring-before($DateTime,'T')" />
</xsl:variable>
<xsl:if test="string-length($date) != 10">
<xsl:value-of select="$DateTime"/>
</xsl:if>
<xsl:if test="string-length($date) = 10">
<xsl:value-of select="$date"/>
</xsl:if>
</xsl:template>
I need to know how to combine both changes to produce the single output element with the renamed node and the formatted date
Thanks,
Brevan
Simply have one template matching dob that does this...
<xsl:template match="dob">
<USER_DOB>
<xsl:call-template name="FormatDate">
<xsl:with-param name="DateTime" select="."/>
</xsl:call-template>
</USER_DOB>
</xsl:template>
My Input XML is having Header, Content and Footer Part. Conversion from XML to JSON works well using XSLT. But I need the output as a three parts as header, Content and Footer:
My Input XML file is:
<header>
<trackingSettings>
<urlcode>W3333</urlcode>
<apiurl>http://mlucenter.com/like/api</apiurl>
</trackingSettings>
</header>
<mlu3_body>
<columnsCount>2</columnsCount>
<lineBackground>linear-gradient(to right, rgba(94, 172, 192, 0) 0%, c4cccf 50%, rgba(94, 172, 192, 0) 100%)</lineBackground>
</mlu3_body>
<footer>
<buttons>
<button/>
</buttons>
<banner/>
</footer>
My XSLT using:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes" method="xml" />
<xsl:template match="*">
<xsl:value-of select="name()"/> : <xsl:call-template name="Properties"/>
</xsl:template>
<xsl:template match="*" mode="ArrayElement">
<xsl:call-template name="Properties"/>
</xsl:template>
<xsl:template name="Properties">
<xsl:variable name="childName" select="name(*[1])"/>
<xsl:choose>
<xsl:when test="not(*|#*)">"<xsl:value-of select="."/>"</xsl:when>
<xsl:when test="count(*[name()=$childName]) > 1">{ "<xsl:value-of select="$childName"/>" :[<xsl:apply-templates select="*" mode="ArrayElement"/>] }</xsl:when>
<xsl:otherwise>{
<xsl:apply-templates select="#*"/>
<xsl:apply-templates select="*"/>
}</xsl:otherwise>
</xsl:choose>
<xsl:if test="following-sibling::*">,</xsl:if>
</xsl:template>
<xsl:template match="#*">"<xsl:value-of select="name()"/>" : '<xsl:value-of select="."/>',
</xsl:template>
</xsl:stylesheet>
Here im using Saxon PE in the oxygen:
I want this XML converted to 3 JSON files named header.json, content.json(mlu3_body) and footer.json in the output.
Is this possible by using XSLT or do I want to keep all input files separately. Please provide some ideas.
Change the XSLT to
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:template match="*">
<xsl:value-of select="name()"/> : <xsl:call-template name="Properties"/>
</xsl:template>
<xsl:template match="*" mode="ArrayElement">
<xsl:call-template name="Properties"/>
</xsl:template>
<xsl:template name="Properties">
<xsl:variable name="childName" select="name(*[1])"/>
<xsl:choose>
<xsl:when test="not(*|#*)">"<xsl:value-of select="."/>"</xsl:when>
<xsl:when test="count(*[name()=$childName]) > 1">{ "<xsl:value-of select="$childName"/>" :[<xsl:apply-templates select="*" mode="ArrayElement"/>] }</xsl:when>
<xsl:otherwise>{
<xsl:apply-templates select="#*"/>
<xsl:apply-templates select="*"/>
}</xsl:otherwise>
</xsl:choose>
<xsl:if test="following-sibling::*">,</xsl:if>
</xsl:template>
<xsl:template match="#*">"<xsl:value-of select="name()"/>" : '<xsl:value-of select="."/>',
</xsl:template>
<xsl:template match="header">
<xsl:result-document href="header.json">
<xsl:next-match/>
</xsl:result-document>
</xsl:template>
<xsl:template match="mlu3_body">
<xsl:result-document href="content.json">
<xsl:next-match/>
</xsl:result-document>
</xsl:template>
<xsl:template match="footer">
<xsl:result-document href="footer.json">
<xsl:next-match/>
</xsl:result-document>
</xsl:template>
</xsl:stylesheet>
and it should generate three result files for those three elements. You will have to edit your question and tell us exactly which result you want if the produced contents is not quite right yet. It is also not clear whether the snippet of XML you have shown is part of a larger document.
I am using Umbraco v6.1.6 and what I want is simply display the images from the media directory I select using media picker.
The content of media directory is as below:
And I have created an XSLT file named ImageSlider.xslt and the content of that file are as below:
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:umb="urn:umbraco.library"
exclude-result-prefixes="umb"
>
<xsl:output method="html" indent="yes" omit-xml-declaration="yes" />
<xsl:param name="currentPage" />
<xsl:template match="/">
<xsl:variable name="media" select="umb:GetMedia(1088, 0)" />
<xsl:if test="$media">
<img src="{$media/umbracoFile}" alt="{$media/altText}" />
</xsl:if>
</xsl:template>
</xsl:stylesheet>
here 1088 is the ID of the banner directory but it is not working at all. I am new to this.
Can anyone please help me ?
I'm assuming you want to select the folder and list all images underneath it. At the moment, your code is just trying to display the folder. You need something like this...
In my example, I'm using a multi-node tree picker and you can select images and folders, rendering out a csv. It will loop through it all and list out all the images
<xsl:for-each select="$source/value">
<xsl:variable name="imageId" select="number(current())" />
<xsl:if test="$imageId > 0">
<xsl:variable name="media" select="umbraco.library:GetMedia($imageId, 0)" />
<xsl:choose>
<xsl:when test="local-name($media) = 'Image'">
<xsl:call-template name="ImageBox">
<xsl:with-param name="imageId" select="$imageId"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="local-name($media) = 'Folder'">
<xsl:call-template name="LoopFolders">
<xsl:with-param name="folderId" select="$imageId"/>
</xsl:call-template>
</xsl:when>
</xsl:choose>
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template name="LoopFolders">
<xsl:param name="folderId"/>
<xsl:variable name="media" select="umbraco.library:GetMedia($folderId, 0)" />
<xsl:variable name="alt" select="$media/#nodeName" />
<div id="gallery">
<xsl:for-each select="umbraco.library:GetMedia($folderId, true())/Image">
<xsl:call-template name="ImageBox">
<xsl:with-param name="imageId" select="number(#id)"/>
</xsl:call-template>
</xsl:for-each>
</div>
</xsl:template>
<xsl:template name="ImageBox">
<xsl:param name="imageId"/>
<xsl:if test="$imageId > 0">
<xsl:variable name="media" select="umbraco.library:GetMedia($imageId, 0)" />
<xsl:if test="$media">
<xsl:variable name="url" select="$media/umbracoFile" />
<xsl:variable name="width" select="$media/umbracoWidth" />
<xsl:variable name="height" select="$media/umbracoHeight" />
<xsl:variable name="alt" select="$media/#nodeName" />
<img src="{$url}" alt="{$alt}" width="{$width}" height="{$height}" />
</xsl:if>
</xsl:if>
</xsl:template>
I'm having trouble publishing an RSS feed from my Umbraco site. I found this Umbraco.TV video and tried to follow the instructions there using an XSLT selector to select all nodes of a give type, like so:
umbraco.library.GetXmlAll()/node [#nodeTypeAlias='Alias]/node
As sugested here but that didn't work. Apparently the schema has changed or something. When this didn't work I looked for a plugin to do this kind of stuff and was amazed to find just 2 plugins, both of them with little-to-no documentation and neither seemed to work (first plugin, second plugin).
So once and for all, I'd like to have a definite answer - how does one publish an RSS feed in Umbraco?
Here's an XSLT that we use for News Items RSS (News Items are under a News Page). Let me know if that helps. I also have versions for Blogs.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:rssdatehelper="urn:rssdatehelper"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:msxml="urn:schemas-microsoft-com:xslt"
xmlns:umbraco.library="urn:umbraco.library" xmlns:Exslt.ExsltCommon="urn:Exslt.ExsltCommon" xmlns:Exslt.ExsltDatesAndTimes="urn:Exslt.ExsltDatesAndTimes" xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath" xmlns:Exslt.ExsltRegularExpressions="urn:Exslt.ExsltRegularExpressions" xmlns:Exslt.ExsltStrings="urn:Exslt.ExsltStrings" xmlns:Exslt.ExsltSets="urn:Exslt.ExsltSets"
exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets ">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:param name="currentPage"/>
<!-- Update these variables to modify the feed -->
<xsl:variable name="RSSNoItems" select="/macro/RSSNoItems"/>
<xsl:variable name="RSSTitle" select="/macro/RSSTitle"/>
<xsl:variable name="SiteURL" select="concat('http://',umbraco.library:RequestServerVariables('HTTP_HOST'))"/>
<xsl:variable name="RSSDescription" select="/macro/RSSDescription"/>
<xsl:variable name="source" select="/macro/source"/>
<!-- This gets all news and events and orders by updateDate to use for the pubDate in RSS feed -->
<xsl:variable name="pubDate">
<xsl:for-each select="umbraco.library:GetXmlNodeById($source)/* [#isDoc and string(umbracoNaviHide) != '1']">
<xsl:sort select="./newsDate" order="descending" />
<xsl:if test="position() = 1">
<xsl:value-of select="./newsDate" />
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:template match="/">
<!-- change the mimetype for the current page to xml -->
<xsl:value-of select="umbraco.library:ChangeContentType('text/xml')"/>
<xsl:text disable-output-escaping="yes"><?xml version="1.0" encoding="UTF-8"?></xsl:text>
<rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
>
<channel>
<title>
<xsl:value-of select="$RSSTitle"/>
</title>
<link>
<xsl:value-of select="$SiteURL"/>
</link>
<pubDate>
<xsl:value-of select="$pubDate"/>
</pubDate>
<generator>umbraco v4</generator>
<description>
<xsl:value-of select="$RSSDescription"/>
</description>
<language>en</language>
<xsl:for-each select="umbraco.library:GetXmlNodeById($source)/* [#isDoc and string(umbracoNaviHide) != '1']">
<xsl:sort select="./newsDate" order="descending" />
<xsl:if test="position() <= $RSSNoItems">
<xsl:call-template name="RSSitem">
<xsl:with-param name="node" select="current()"/>
</xsl:call-template>
</xsl:if>
</xsl:for-each>
</channel>
</rss>
</xsl:template>
<xsl:template match="node">
<xsl:if test="position() <= $RSSNoItems">
<item>
<title>
<xsl:value-of select="#nodeName"/>
</title>
<link>
<xsl:value-of select="$SiteURL"/>
<xsl:value-of select="umbraco.library:NiceUrl(#id)"/>
</link>
<pubDate>
<xsl:value-of select="umbraco.library:FormatDateTime(./newsDate,'r')" />
</pubDate>
<guid>
<xsl:value-of select="$SiteURL"/>
<xsl:value-of select="umbraco.library:NiceUrl(#id)"/>
</guid>
<content:encoded>
<xsl:value-of select="concat('<![CDATA[ ', ./bodyText,']]>')" disable-output-escaping="yes"/>
</content:encoded>
</item>
</xsl:if>
</xsl:template>
<xsl:template name="RSSitem">
<xsl:param name="node"/>
<item>
<title>
<xsl:value-of select="$node/#nodeName"/>
</title>
<link>
<xsl:value-of select="$SiteURL"/><xsl:value-of select="umbraco.library:NiceUrl($node/#id)"/>
</link>
<pubDate>
<xsl:value-of select="umbraco.library:FormatDateTime(./newsDate,'r')"/>
</pubDate>
<dc:creator><xsl:value-of select="#writerName"/></dc:creator>
<xsl:for-each select="umbraco.library:Split($node/categories, ',')/value">
<xsl:sort data-type="text" order="ascending"/>
<category>
<xsl:value-of select="current()"/>
</category>
</xsl:for-each>
<guid>
<xsl:value-of select="$SiteURL"/><xsl:value-of select="umbraco.library:NiceUrl($node/#id)"/>
</guid>
<description>
<xsl:value-of select="concat('<![CDATA[ ', $node/summary,']]>')" disable-output-escaping="yes"/>
</description>
<content:encoded>
<xsl:value-of select="concat('<![CDATA[ ', $node/bodyText,']]>')" disable-output-escaping="yes"/>
</content:encoded>
</item>
</xsl:template>
</xsl:stylesheet>