Find item in function output - xslt

I have two functions:
GetHomeXml() -> returns a collection of pages with a custom meta type
SiteMapXml() -> standard sitemap xml
SiteMapXml() has a property (isCurrent) that gets returned if the page is the current page. I need to determine if the name of the page appears in GetHomeXml(), and whether the node in GetHomeXml() has an Image.FileName property assigned to it.
I can get both returned, but I cannot figure out the XSL to accomplish this. Following is what I have so far:
<xsl:param name="currentPage" select="/in:inputs/in:result[#name='SitemapXml']/Page/#iscurrent" />
<xsl:for-each select="/in:inputs/in:result[#name='GetHomeXml']/Image">
<xsl:if test="#Image.PageTitle = $currentPage.Title">
<img src="#Image.FileName" />
</xsl:if>
</xsl:for-each>
I created a custom meta data entry, and added 3 fields to it {IsTab, Image, Color}. I want to determine that if the current page contains an Image field, and the Page.Title assigned to it, is the same as the current page, to render the designated image (it's a data reference field, with an image lookup property to the images directory) into the tag.
But this code does not seem to return anything?
Update:
The XML that is returned for GetHomeXml() is as follows:
<!-- Function Call Result (0 ms), XPath /in:inputs/in:result[#name='GetHomeXml']/IsTab -->
<in:result name="GetHomeXml">
<IsTab Id="9eba448e-9a30-478e-81b2-530bc7da2545" IsTab="true" BackgroundImg="MediaArchive:34f9be39-8273-4960-8cc6-e6b76f34e6ac" BackgroundImg.FileName="home-group-2.png" PageId.Title="Contact Us" xmlns=""/>
<IsTab Id="a46e2e98-ffcd-4675-8840-389d1a7f46ca" IsTab="true" PageId.Title="Welcome" xmlns=""/>
<IsTab Id="c76fa101-8c63-46e2-9431-e18ce875866d" IsTab="false" PageId.Title="What we do" xmlns=""/>
I want to get the name of the image, based on the current page (PageId.Title) I need to match back to the returned value associated with the current page in SiteMapXml:
<!-- Function Call Result (0 ms), XPath /in:inputs/in:result[#name='SitemapXml']/Page -->
<in:result name="SitemapXml">
<Page Id="62c66cb6-b2ec-4469-b0d7-54bc61b22c20" Title="Home" MenuTitle="Home" UrlTitle="Home" Description="Default web site for... Please do not change any of the settings for this site. Add, modify and delete pages underneath this web site, but do no touch this site." ChangedDate="2011-12-04T22:36:33.2651194+02:00" ChangedBy="admin" URL="/Home/c1mode(unpublished)" Depth="1" xmlns="">
<Page Id="041c7d66-60cd-4098-ac98-728c0db111a1" Title="Welcome" MenuTitle="Welcome" UrlTitle="Welcome" Description="" ChangedDate="2011-12-04T22:38:06.2815949+02:00" ChangedBy="admin" URL="/Home/Welcome/c1mode(unpublished)" Depth="2"/>
<Page Id="8ae4d8a5-f4d9-43ed-85de-90b6d3a6f0b8" Title="Contact Us" MenuTitle="Contact Us" UrlTitle="Contact-Us" Description="" ChangedDate="2011-12-04T22:54:10.1503871+02:00" ChangedBy="admin" URL="/Home/Contact-Us/c1mode(unpublished)" isopen="true" iscurrent="true" Depth="2"/>
<Page Id="ed5560a4-140b-4851-ac19-5ddc6c66a770" Title="What we do" MenuTitle="What we do" UrlTitle="What-we-do" Description="" ChangedDate="2011-11-28T07:23:25.8851421+02:00" ChangedBy="admin" URL="/Home/What-we-do/c1mode(unpublished)" Depth="2"/>
</Page>
</in:result>
</in:result>

Instead of looping through the resultset, use a xpath predicate to match the page by title. For example, the URL of the welcome page would be given by:
$pages[#Page.Title='Welcome']/#URL
Here is a complete XSLT which shows the URLs for the HomeXML pages:
<xsl:param name="homeXml" select="/in:inputs/in:result[#name='GetHomeXml']/IsTab" />
<xsl:param name="sitemap" select="/in:inputs/in:result[#name='SitemapXml']/Page" />
<xsl:template match="/">
<html>
<head>
<!-- markup placed here will be shown in the head section of the rendered page -->
</head>
<body>
<xsl:for-each select="$homeXml">
<xsl:variable name="pageTitle" select="#PageId.Title" />
<xsl:variable name="sitemapPage" select="$sitemap//Page[#Title=$pageTitle]/#URL" />
<xsl:value-of select="$sitemapPage" />
</xsl:for-each>
</body>
</html>
</xsl:template>
Corresponding XsltCake (like JsFiddle, but for Xslt)

Related

Sitecore XSLHelper.fld Method not working as expected

I'm having some troubles with XSLHelper.fld method. I have a very simple XSLT file that I am trying to access sub-values that are inside my Sitecore image item.
Code Sample:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:sc="http://www.sitecore.net/sc"
xmlns:dot="http://www.sitecore.net/dot"
exclude-result-prefixes="dot sc">
<!-- output directives -->
<xsl:output method="html" indent="no" encoding="UTF-8" />
<!-- parameters -->
<xsl:param name="lang" select="'en'"/>
<xsl:param name="id" select="''"/>
<xsl:param name="sc_item"/>
<xsl:param name="sc_currentitem"/>
<!-- variables -->
<!-- Uncomment one of the following lines if you need a "home" variable in you code -->
<!--<xsl:variable name="home" select="sc:item('/sitecore/content/home',.)" />-->
<!--<xsl:variable name="home" select="/*/item[#key='content']/item[#key='home']" />-->
<!--<xsl:variable name="home" select="$sc_currentitem/ancestor-or-self::item[#template='site root']" />-->
<!-- entry point -->
<xsl:template match="*">
<xsl:apply-templates select="$sc_item" mode="main"/>
</xsl:template>
<!--==============================================================-->
<!-- main -->
<!--==============================================================-->
<xsl:template match="*" mode="main">
TEST BACKGROUND IMAGE
<br/>
ALT: <br/>
<xsl:value-of select="sc:fld('background',.,'alt')"/>
<br/>
SRC: <br/>
<xsl:value-of select="sc:fld('background',.,'src')"/>
<br/>
Field SRC: <br/>
<xsl:value-of select="sc:field('background',.,'src')"/>
</xsl:template>
</xsl:stylesheet>
When I test the following code, the results are strange as can be seen from the following screenshot:
You can clearly see that the alt field has a value and the src field is empty. So I definitely have access to my Sitecore image item but cannot get access to the src field.....
Can anyone shed some light on why the src field is empty?
Regards,
Comic Coder
As I stated on your other question, there is no longer a src attribute in the raw value of image fields. The alt attribute exists if you modify the Alternate Text in the properties of the image field or it will fall back to the alt text on the image item in the media library.
The sc:field method uses a field renderer to output a full <img> tag. The third parameter to that method is supposed to be for additional parameters like width and height or additional attributes. It should be formatted as a query string (e.g. width=150&height=100). It is probably just ignoring the src value that you are passing because it isn't valid.

Use dynamically created xsl:variable in select (Sharepoint 2013)

I'm using xslt 1.0 to transform a Sharepoint 2013 Data View.
The data source consists of 3 joined lists:
ISOList
Threat_Catalogue (has a lookup (multiple) to ISOList)
Risks (has a lookup (single) to Threat_Catalogue)
I'm looping thru items in ISOList, and want to show all Risks that are relevant for this specific item. The logic being: First find Threats related to the specific item in ISOList, and then find Risks related to one of those Threats.
So I'm calling a template with the item ID (ISORef) from ISOList as a parameter - like so:
<xsl:template name="Risks">
<xsl:param name="ISORef" />
<!-- add extra info to string, so it only selects relevant items -->
<xsl:variable name="ISORefString" select="concat('&ID=',$ISORef,'&RootFolder')"/>
<!-- get relevant threats -->
<xsl:variable name="SelectedThreats" select="/dsQueryResponse/Threat_Catalogue/Rows/Row[contains(#ISO_x0020_Reference, $ISORefString)]"/>
<!-- Create variable, that contains all ID's in Threat_Catalogue that are relevant -->
<xsl:variable name="ListThreats"><xsl:for-each select="$SelectedThreats">=<xsl:value-of select="#ID"/>&</xsl:for-each></xsl:variable>
<!-- Variable - just to illustrate problem -->
<xsl:variable name="ListThreatsAlternative" select="$ListThreats" />
<!-- this is where I'm trying to use variable to get relevant risks, but fails -->
<!-- Old: Didn't Work, has been replaced -->
<!--
<xsl:variable name="SelectedRisks" select="/dsQueryResponse/Risks/Rows/Row[contains($ListThreats, substring-before(substring-after(#Threat, 'ID'), 'RootFolder'))]"/>
-->
<!-- New: Works as intended -->
<xsl:variable name="SelectedRisks" select="/dsQueryResponse/Risks/Rows/Row[contains($ListThreats, substring-before(substring-after(#Threat, 'ID'), 'RootFolder')) and $ListThreats != '' and #Threat != '']"/>
<!-- Example output: -->
Original: <xsl:value-of select="$ListThreats" /> <!-- contains: '=118&' --> <br/>
Alternative: <xsl:value-of select="$ListThreatsAlternative" /> <!-- empty -->
</xsl:template>
The problem is that variable ListThreats appears as an empty string when used as a criteria in the select for either SelectedRisks or ListThreatsAlternative.
*Edited:
The source XML is generated by Sharepoint. I don't know how to get the XML of the specific data source, but below I've added the XML from the Risks list. I've shortened down the XML source substantially, but hopefully it is sufficient.
Also - there are some significant differences in source XML and what Sharepoint presents in a list. Especially when it comes to the lookup-fields.
Example:
When Sharepoint presents the content:
https://xxx.xxx.xxx.com/sites/xxx_xxx/ISMS/_layouts/15/listform.aspx?PageType=4&ListId={4ab4bbff-588b-4c06-9685-c814cdefd59f}&ID=56&RootFolder=*', RefreshPage); return false;" href="https://xxx.xxx.xxx.com/sites/xxx_xxx/ISMS/_layouts/15/listform.aspx?PageType=4&ListId={4ab4bbff-588b-4c06-9685-c814cdefd59f}&ID=56&RootFolder=*">Hackers: 14. Password Cracking
When similar content is shown in source XML:
55;#Hackers: 13. Malware
This is the XML source (shortened):
<xml xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema">
<s:Schema id="RowsetSchema">
<s:ElementType name="row" content="eltOnly" rs:CommandTimeout="30">
<s:AttributeType name="ows_ID" rs:name="ID" rs:number="1">
<s:datatype dt:type="i4" dt:maxLength="4"/>
</s:AttributeType>
<s:AttributeType name="ows_LinkTitle" rs:name="Risk Title" rs:number="2">
<s:datatype dt:type="string" dt:maxLength="512"/>
</s:AttributeType>
<s:AttributeType name="ows_Threat" rs:name="Threat" rs:number="15">
<s:datatype dt:type="variant" dt:lookup="true" dt:maxLength="8009"/>
</s:AttributeType>
</s:ElementType>
</s:Schema>
<rs:data>
<z:row ows_ID="72" ows_LinkTitle="Test risk" ows_Threat="55;#Hackers: 13. Malware" />
</rs:data>
</xml>
Found the answer, stupid mistake in the select. Edited in OP.

How to output xml elements in xslt when output method is set to text?

I am going to create an ASP.NET user control (ascx) from input XML using xslt.
Because there is some strange design-agency html involved the output is not granted to be valid html or even xhtml, so telling from answers to my other question I need to use the output method text. The other reason is that when I use xml or html the output is cluttered with xmlns-attributes I cannot prevent without changing the output to text.
When the output would be XML, I would use a template like this:
<xsl:template match="TextField">
<xsl:text>
<![CDATA[<someInvalid><stuff><fromAgency /></somInvalid>]]>
</xsl:text>
<xsl:apply-templates select="./Label" />
<asp:TextBox ID="{#id}" runat="server">
<xsl:if test="#defaultValue">
<xsl:attribute name="value">
<xsl:value-of select="#defaultValue"/>
</xsl:attribute>
</xsl:if>
</asp:TextBox>
<xsl:text><![CDATA[</stuff>]]></xsl:text>
<xsl:copy-of select="$br"/>
</xsl:template>
now, when I switch the output method to text, nothing is written to the result at all.
Obviously the text mode simply ignores all xml in the template. How can I tweak my template to output these elements even when the output method is set to text?
Clarification: The <asp:TextBox>- Tag with its attributes and values is the desired output of this transformation, but when changing output mode to text this is errantly ommited from the output.
Update: Here is a full input XML:
<?xml version="1.0" encoding="utf-8" ?>
<Form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="XmlForm.xsd">
<Validation enabled="false" enableValidationSummary="true" />
<FieldSet>
<TextField id="firstInput" css-class="textfield-css-class" />
<TextField id="secondInput" defaultValue="Wrdlbmrpft">
<Label translatable="true" >Label Text</Label>
</TextField>
</FieldSet>
</Form>
The full desired output would be like this:
<%# Control Language="C#" AutoEventWireup="true" Inherits="DevelopmentWeb.WebUserControl1" %>
<someInvalid><stuff><fromAgency /></somInvalid>
<asp:TextBox runat="server" ID="firstInput" CssClass="textfield-css-class"></asp:TextBox>
</stuff>
<someInvalid><stuff><fromAgency /></somInvalid>
<asp:Label runat="server" AssociatedControlID="secondInput">Label Text</asp:Label>
<asp:TextBox runat="server" ID="secondInput">Wrdlbrmpft</asp:TextBox>
</stuff>

XSLT: output list on condition of attribute of parent-node

I'm struggling to create a list to be displayed on the condition of the parent node ('folder') with attribute 'folded' set to either 'yes' or 'no'.
The result shall display the first two levels of the list only and not the third level as below.
1st. Level: display
2nd. Level: display
3rd. Level: NO display
The idea is to check the 'folder'-attribute <folder folded="yes"> with <xsl:if test="not(parent::yes)">.
That should qualify for the 3rd. Level to NOT being displayed, but somehow it doesn't do what I want it to do.
I probably use the wrong construct and/or syntax.
Assistance is highly appreciated, thanks.
The XML structure with some content:
<xbel>
<folder folded="yes">
<level>1</level>
<title>bookmarks</title>
<desc>my bookmarks</desc>
<folder folded="no">
<level>2</level>
<title>Android</title>
<desc>my Android</desc>
<bookmark href="http://www.phonesreview.co.uk/">
<title>HTC Sync 3.0.5422 Update: Aria, Desire, Hero, Legend</title>
<desc>The new HTC Sync 3.0.5422 update will be most welcome...</desc>
</bookmark>
<folder folded="no">
<level>3</level>
<title>Apps</title>
<desc>Android Apps</desc>
<bookmark href="http://www.androidzoom.com/">
<title>Android Communication Apps</title>
<desc>Download Communication Apps for Android.</desc>
</bookmark>
<bookmark href="http://www.htc.com/">
<title>HTC - Android</title>
<desc>Apps for HTC-Android.</desc>
</bookmark>
</folder>
</folder>
</folder>
</xbel>
The XSLT:
<!--creates a nested list of elements named 'folder'-->
<xsl:template match="folder" mode="linklist">
<li>
<xsl:if test="folder/level = 2">
Level:<xsl:value-of select="level"/> /
Title:<xsl:value-of select="title"/> /
Desc:<xsl:value-of select="desc"/>
<ul>
<xsl:apply-templates mode="linklist" />
</ul>
</xsl:if>
</li>
</xsl:template>
<xsl:template match="bookmark" mode="linklist">
<li> <!-- this bookmark is just another item in the list of bookmarks -->
<!-- the title -->
<a rel="nofollow" href="{#href}"><xsl:value-of select="title"/></a>
<!-- the description -->
<xsl:if test="desc">
<span class="bookmarkDesc">
<xsl:value-of select="desc"/>
</span>
</xsl:if>
</li>
</xsl:template>
The Stylesheet HTML
<body>
<ul>
<xsl:apply-templates mode="linklist" />
</ul>
</body>
The generated output (levels:1-3)
Level:1 / Title:bookmarks / Desc:my bookmarks
Level:2 / Title:Android / Desc:my Android
HTC Sync 3.0.5422 Update: Aria, Desire, Hero, Legend ...
Level:3 / Title:Apps / Desc:Android Apps
Android Communication AppsDownload Communication Apps for Android.
HTC - AndroidApps for HTC-Android.
The anticipated output: (levels: 1-2)
Level:1 / Title:bookmarks / Desc:my bookmarks
Level:2 / Title:Android / Desc:my Android
HTC Sync 3.0.5422 Update: Aria, Desire, Hero, Legend ...
I tried this template, but that outputs the last two nodes, I need the two first nodes.
<xsl:template match="folder[parent::folder/#folded = 'yes']" mode="linklist">
The simplest possible change you could make to prevent processing of unfolded folder elements is to add an empty template that swallows them (i.e. produces no output):
<xsl:template match="folder[#folded='no']" mode="linklist"/>
All folder elements not having a folded attribute equal to no will be processed using your existing template; those that do will be captured by this new one.
If instead you want to process each folder element having either its own folded attribute equal to yes or that of its parent (as in the updated XML example), then use the following template:
<xsl:template match="folder[#folded='yes' or ../#folded='yes']" mode="linklist">
<!-- body elided -->
</xsl:template>
You'll probably also want to include an empty template for hiding all other folder elements:
<xsl:template match="folder" mode="linklist" />

Left Section Menu - Retraive Items in Sitecore

I have the following XSLT Section Menu Code which working correctly to retreive items. But I'd like to replaced the items query by items name how ?
<!--<xsl:if test="contains($EnabledTemplates, concat('!', #template, '!')) ">-->
<xsl:for-each select="$root/item[contains($EnabledTemplates, concat('!', #template, '!'))]">
<xsl:sort select="#sortorder" data-type="number" />
<xsl:variable name="IsHaveChild" select="boolean(./item)" />
<xsl:variable name="IsSelected" select="boolean(./descendant-or-self::item[#id=$sc_currentitem/#id])" />
<xsl:variable name="IsShow" select="boolean(sc:fld($IsHideFieldName,.)!=1)" />
<xsl:variable name="IsCurrent" select="boolean(#id=$sc_currentitem/#id)" />
<sc:sec />
Do you want to filter items by name?
Try something like this:
[contains(#name, 'some text')]
For your querying you can choose between XPath and Sitecore query. The latter is a Sitecore implementation of XPath which is more readable and allows you to use the item names instead of XPath syntax.
Sitecore query however cannot be put directly in a select attribute in your XSL elements, it only works in the Sitecore XSL helper functions like sc:item (please also not the . in the sc:item function to specify the context item in which the query needs to be applied, . stands for current item).
<!-- using XPath -->
<xsl:value-of select="/item[#key='sitecore']/item[#key='content']" />
<!-- using Sitecore query -->
<xsl:value-of select="sc:item('/sitecore/content', .)" />