Display images from tree list in Sitecore - xslt

In Sitecore, I have a tree list for the user to select certain images. I would like to use the presentation api to display the images that the user selects. While looking through the Presentation Component XSL reference guide, I found this code:
<xsl:variable name="slideShow" select="/*/item[#key='content']/item[#key='home']/item[#key='Foundation']/item[#key='Landing Pages']/item[#key='Legends Trail Ride']" />
<xsl:variable name="mediaid" select="sc:fld('Slide Show',$slideShow,'mediaid')" />
<xsl:if test="$mediaid">
<xsl:variable name="mediaitem" select="sc:item($mediaid,$slideShow)" />
<xsl:if test="$mediaitem">
<a href="{concat('/',sc:GetMediaUrl ($mediaitem))}">
<xsl:choose>
<xsl:when test="sc:fld ('title',$mediaitem)">
<sc:text field="title" select="$mediaitem" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$mediaitem/#name" />
</xsl:otherwise>
</xsl:choose>
</a>
</xsl:if>
</xsl:if>
The page will display so technically there isn't anything wrong with the code but the image still aren't showing. Is this code going in the right direction or is there an alternative way to display images from a tree list?

If your site is using the 'web' database, make sure you have published all of your media items or they won't display.

A typical scenario for your case would be to check if all templates and subtemplates of the specific items on which those images are attached are published. If this is done check your media library folders and media items in those folders. You have to make sure the folder in which you added the images is also published. What you can do to verify the above after you have published is login to the 'desktop' mode of Sitecore and change the database (bottom right corner) to 'web'. Then find all of the described items and see if everything is really published. Most of the times you will encounter issues like this it will actually be publishing.

Related

Viewing an uploaded item in DSpace 4.2 xmlui

This is how the my search results page of DSpace looks like :
On clicking the item a new page opens up showing its description:
The description page opens the file upon clicking View/Open. Is it possible to directly open the file upon clicking its title on the results page? I want to skip the item description page.
As per my understanding this is the Java file which is called to render items. Do I need to make changes to this file? Or is it possible to achieve what I want by simply modifying the sitemap and xsl files?
The code that generates the thumbnail image is here.
https://github.com/DSpace/DSpace/blob/dspace-6_x/dspace-xmlui/src/main/webapp/themes/dri2xhtml/General-Handler.xsl#L34-L47
You could create similar logic to create an href to the original bitstream.
Look at the XML in /metadata/handle/xxx/yyy/mets.xml where xxx/yyy is your item handle. You should see the information that will point you to the original bitstream.
As was said in the comments, the xsl template to modify is the "itemSummaryList" in discovery.xsl
Replace that href value with $metsDoc//mets:FLocat[#LOCTYPE='URL']/#xlink:href"
<xsl:element name="a">
<xsl:attribute name="href">
<xsl:value-of select="$metsDoc//mets:FLocat[#LOCTYPE='URL']/#xlink:href"/>
</xsl:attribute>
<xsl:choose>
<xsl:when test="dri:list[#n=(concat($handle, ':dc.title')) and descendant::text()]">
<xsl:apply-templates select="dri:list[#n=(concat($handle, ':dc.title'))]/dri:item"/>
</xsl:when>
<xsl:otherwise>
<i18n:text>xmlui.dri2xhtml.METS-1.0.no-title</i18n:text>
</xsl:otherwise>
</xsl:choose>
</xsl:element>
I was able to achieve what I wanted with help from Antoine Snyers, terrywb and this link. As pointed out by terrywb the information which I needed to read, i.e, the bitstream address of the uploaded file, was stored in the metsDoc. Here's a screenshot of my metsDoc with the fileSec expanded:
To be able to access the fileSec of the metsDoc I changed this line in discovery.xsl and this line in common.xsl to <xsl:text>?sections=dmdSec,fileSec&fileGrpTypes=ORIGINAL,THUMBNAIL</xsl:text>.
Then I added/modified the following code to the itemSummaryList in discovery.xsl so that the title hyperlink now points to the file bitstream.
<xsl:variable name="filetype">
<xsl:value-of select="$metsDoc/mets:METS/mets:fileSec/mets:fileGrp[#USE='CONTENT']"/>
</xsl:variable>
<xsl:variable name="fileurl">
<xsl:value-of select="$metsDoc/mets:METS/mets:fileSec/mets:fileGrp[#USE='CONTENT']/mets:file/mets:FLocat[#LOCTYPE='URL']/#xlink:href"/>
</xsl:variable>
<div class="artifact-title">
<xsl:element name="a">
<xsl:attribute name="href">
<xsl:choose>
<xsl:when test="$metsDoc/mets:METS/mets:dmdSec/mets:mdWrap/mets:xmlData/dim:dim/#withdrawn">
<xsl:value-of select="$metsDoc/mets:METS/#OBJEDIT"/>
</xsl:when>
<xsl:when test="$filetype">
<xsl:value-of select="$fileurl"/>
</xsl:when>
</xsl:choose>
</xsl:attribute>
Similarly, I also made changes to item-list.xsl file, and added this line <xsl:apply-templates select="mets:fileSec/mets:fileGrp[#USE='CONTENT']"
mode="itemSummaryList-DIM"/> to the template itemSummaryList-DIM.
So finally I got my desired result:
As visible in the inspector, the href attribute of the title now points to the original bitstream of the file :)

Sitecore rendering: searching of first item by condition using fields

I have few items with parent/children dependencies:
Item1 -> Item2 -> Item3
They have fields with the same name: "Main Info". Some of them have this field filled, some of them with empty "Main Info". Main goal: if page with filled "Main Info" selected - show this info. If page with empty "Main Info" selected - show info from ancestor.
So i have rendering:
<xsl:variable name="home" select="$sc_currentitem/ancestor-or-self::*[contains(#template, 'page') and #Main Info != '']" />
<!-- entry point -->
<xsl:template match="*">
<xsl:apply-templates select="$home" mode="main"/>
</xsl:template>
<xsl:template match="*" mode="main">
<sc:text field="Right Footer Text" />
</xsl:template>
This shows nothing.
<xsl:variable name="home" select="$sc_currentitem/ancestor-or-self::*[contains(#template, 'page')]" />
<xsl:template match="*">
<xsl:apply-templates select="$home" mode="main"/>
</xsl:template>
<xsl:template match="*" mode="main">
<sc:text field="Right Footer Text" />
</xsl:template>
This shows "Main Info" from every ancestor of selected item.
How can i get only one "Main Info"? From selected item if this field isn't empty or from first parent item with "Main Info" filled.
I really believe this demonstrates why you should be looking at writing your components in C# as opposed to wasting time trying to "hack" a solution in via XSLT. Sure, you can write your own extension if you like - but let's consider how little code this would be to begin with.
On your .ASCX file, you would have this:
<sc:Text runat="server" ID="sctMainInfo" Field="main info" />
And in your .cs codebehind/codebeside:
Sitecore.Data.Item myItem = Sitecore.Context.Item; // Should be your Datasource item
while (string.IsNullOrWhiteSpace(myItem["main info"]))
{
myItem = myItem.Parent; // you need to add a check here,
// so you don't move up past your Site Root node
}
sctMainInfo.Item = myItem;
By far simpler than a combined XSLT/XSL Helper approach, and performance will be a lot better.
One last thing. The very premise of your rendering has a problem. You shouldn't really be crawling through the item hierarchy to find content for your component, you prevent any possibilities for performing M/V testing or personalizing the component. This is a story for a different day however.
Performance-wise you might not want to use the ancestor-or-self selector. If you have a lot of items and a deep tree its bad for performance.
I think I'd either create an <xsl:choose> like so:
<xsl:choose>
<xsl:when test="sc:fld('main info',.)!=''">
<sc:text field="main info" select="." /> <!-- Display main info from item -->
</xsl:when>
<xsl:otherwise>
<sc:text field="main info" select=".." /> <!-- Display main info from parent -->
</xsl:otherwise>
</xsl:choose>
Of course, if there's a possibility that it's not the parent but the parents parent (and so forth) that has the main info I'd make it simpler by creating my own XSL Extension.
You can read more on XSL Extensions on this article by Jens Mikkelsen.

Two microalias in single umbraco.library:RenderMacroContent method

For the desktop site I have a content in Umbraco where <p><?UMBRACO_MACRO macroAlias="StoryDesc" /></p> refers to XSLTName field
I am making a call from one XSLT to StroyDesc XSLT as
<xsl:variable name="StoryXSLT" select="$currentPage/XSLTName"/>
<xsl:value-of select="umbraco.library:RenderMacroContent(StoryXSLT, $currentPage/id)" />
Now for mobile site I have different XSLT MobileStoryDesc instead of StoryDesc. I cannot add a new separate content like <p><?UMBRACO_MACRO macroAlias="MobileStoryDesc" /></p>. But I can alter the existing content without affecting the present desktop site.
Is it possible to make a XSLT call. Please suggest me a solution. Thanks in advance.
I might not quite understand you, so apologies if I'm mixed up.
Why not create a MobileStoryXSLT & a DesktopStoryXSLT and use the StoryDescXSLT to choose which one to use?
Something like:
<xsl:if test="...desktop...">
<xsl:value-of select="umbraco.library:RenderMacroContent(DesktopStoryXSLT, $currentPage/id)" />
</xsl:if>
<xsl:if test="... mobile ...">
<xsl:value-of select="umbraco.library:RenderMacroContent(MobileStoryXSLT, $currentPage/id)" />
</xsl:if>

umbraco: get USER properties, NOT member properties in XSLT

Here's my scenario:
Added an Author Picker to the default umbBlogPost (from the blog4umbraco package) which gives me access to the author's id in an XSLT macro
The Author Picker is pulling up a list of umbraco users, not members
I want to the display the author's username in xslt output
I've tried several different ways based on Google searches which all seem to be using the Membership API, such as umbraco.libary:GetMember and umbraco.library:GetMemberName which is not working, again, as I am dealing with umbraco users, not members. There doesn't appear to be any user equivalent methods, i.e., umbraco.libary:GetUser or umbraco.library:GetUserName.
Does anyone know how I can get user properties in an xslt macro? I am using version 4.7.2. Also, while I'm currently working with xslt, if this can be done with a Razor macro (if supported in 4.7.2?) I am open to seeing this approach as well. Thanks.
Taking a look directly in the XML that the XSLTs run off (~/App_Data/umbraco.config), I found the following attributes:
<Site
writerID="0"
creatorID="0"
writerName="John Smith"
creatorName="John Smith"
/>
So you should be able to reference those in the XSLT with the following:
<xsl:value-of select="$currentPage/#writerName" />
If you need the other properties of the user, you'll probably need to write your own library, which could then be accessed by the XSLT files. Just look at how umbraco.library is included at the top of the file.
Ucomponents provides an XSLT solution
<xsl:choose>
<xsl:when test="$currentPage/bodyAuthor != ''">
<xsl:value-of select="ucomponents.cms:GetUserName($currentPage/bodyAuthor)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$currentPage/#writerName" />
</xsl:otherwise>
</xsl:choose>
I ended up solving this by writing a Razor macro. The key was to add #using umbraco.BusinessLogic; at the beginning of the macro. This namespace provides the API required to get user data as opposed to member data.
For anyone interested, here's the macro I wrote:
#using umbraco.BusinessLogic;
#inherits umbraco.MacroEngines.DynamicNodeContext
<div>
<h1>
From Our Blog
</h1>
<ul>
#foreach(var i in #Model.AncestorOrSelf("umbHomepage").Descendants("umbBlogPost").OrderBy("PostDate desc").Take(5))
{
<li>
<p>
#i.Name<br />
by #umbraco.BusinessLogic.User.GetUser(Int32.Parse(i.blogAuthor)).Name on #i.PostDate.ToString("MMM dd, yyyy")
</p>
</li>
}
</ul>
</div>

Next Previous navigation in news article for umbraco

This is driving me a little crazy (been trying to do this for quite some time)
I'm trying to get some xpath code working that will display next and previous links, which will take you to the next newsItem and once it gets to newsItem4, then the next button disappears.
<newsArea>
<newsItem1></newsItem1> <----- currentPage
<newsItem2></newsItem2>
<newsItem3></newsItem3>
<newsItem4></newsItem4>
</newsArea>
I can list al the newsItems whilst on a news item with
<xsl:for-each select="$currentPage/../*">
<h2><xsl:value-of select="#nodeName"/></h2>
</xsl:for-each>
and i can count how many items i have
<xsl:value-of select="count($currentPage/../*)-1"/>
but i dont know how to move to the next news item, or how to tell it when to stop showing the next node when it comes to the end of the newsItems (one example just jummped to another leve)
Any help would be really really appreciated.
Thanks
Tim
Take a look at the paging sample from this blog post: http://www.nibble.be/?p=11
That should give you an idea of how it works. You could always set your page size to 1.
Also, there is a package based on that method: http://our.umbraco.org/projects/developer-tools/paging-xslt
That should get you on the right path.
You could easily create a "Page Navigation" macro to add to the bottom of any template you want it, XSLT would be as follows:
<xsl:template match="/">
<!-- if there's a previous page -->
<xsl:if test="$currentPage/preceding-sibling::*[1]">
< Prev
</xsl:if>
<!-- if there's next and previous, show divider -->
<xsl:if test="$currentPage/preceding-sibling::*[1] and $currentPage/following-sibling::*[1]">
<xsl:text> | </xsl:text>
</xsl:if>
<!-- if there's a next page -->
<xsl:if test="$currentPage/following-sibling::*[1]">
Next >
</xsl:if>
</xsl:template>