tags:

views:

318

answers:

5

I have the following for-each select;

"sc:item($myFolder,.)/descendant::item [@template='myTemplate']". According to Sitecore's own profiler this returns crawls through 16.000 items, although there are only approx 1700 items with the mentioned template.

Could this be optimized - if so, how?

A: 

If you can convert your xsl:for-each to a xsl:template, it should help with performance, as most XSLT processors are optimized for template matching.

Oded
Do you have an example of this? It's a basic for-each that select a list of items based on the template, and then sort by a number field and shows the 3 top (so its basicly a top 3 list)
kastru
I forgot to mention that i also have this;<xsl:variable name="root" select="(ancestor::*/item [@template='folderStart'])[last()]" />which i use for finding the item that has the path to myFolder defined. That could be a potential killer, or?
kastru
A: 

The for-each is not the problem, but the XPath query used is.

The descendant axis is usually expensive because it requires the engine to do a complete deep search, without the possibility of eliminating paths. So you may want to replace this with a pattern which restricts the required search path.

Maybe using keys would help, but without deeper knowledge of the XML to be processed and the operations performed this is hard to tell.

Lucero
any suggestions?
kastru
A: 

"Do you have an example of this? It's a basic for-each that select a list of items based on the template, and then sort by a number field and shows the 3 top (so its basicly a top 3 list)"

Based on what you're trying to accomplish, I think you would be much better off putting this logic into a save handler and organizing your items when a content author saves an item based on the template you're looking for.

For example (and this is a very rough example), create a "Top 3" folder in your content tree. Then, write a save handler that checks the TemplateID of an item as it's being saved. If the saved item's TemplateID matches the TemplateID you're looking for, select all the items in your tree based on the TemplateID and process them with whatever sorting logic you need. As you find an item that belongs in the "Top 3" folder, move the item to the "Top 3" folder.

Then, in your rendering code, you simply have to get the "Top 3" folder and retrieve it's children. This will be MUCH faster than attempting to look through 1700 items every time the rendering is loaded.

aweber1
A: 

It can be optimised, but the easiest approach would be to reorganize your content architecture to better suit your needs and requirements.

Straight from XSLT there is no easy solution, but with a bit of coding you can fAirly easily get all your content items based on your specific template. It would look something like this:

Item myTemplate = Sitecore.Context.Database.GetItem( "id-of-your-template" );
LinkItem[] li = Sitecore.Globals.LinkDataBase.GetReferrers( myTemplate );
// li now holds a list of LinkItem for items that are based on your template
List<Item> myItems = new List<Item>();
foreach( LinkItem l in li )
  myItems.Add( li.SourceItem() );
// your additional processing/filtering here

Keep in mind, this is a very non-specific example of how this can be achieved. I would need to know a lot more about your solution to come up with a better response. And I still feel, the best approach is probably still to look at your information architecture.

Mark Cassidy
A: 

If I need to do any particularly difficult searches in an XSLT, then I often define an XSLT helper method to perform the search, as the .Net API has much better facilities available.

In your case, I'd consider creating a .Net function to do the job, either using the Link Manager (as Mark Cassidy suggests) or using Sitecore fast queries to retrieve the items (fast queries are parsed and run as SQL queries).

To register a class as an XML Extension Method library, open web.config, locate the /configuration/sitecore/xslExtensions node and add an entry with your class' full type name and an XML namespace (the URL doesn't actually have to exist).

To use your function, register it in the namespaces at the top of your XSLT (and remember to add the namespace to the exclude-result-prefixes stylesheet attribute). You should then be able to call `namespace:YourFunction().

For more detailed information on XSLT extension methods, see the presentation component reference, page 40.

Matt