Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Dirk De Grave 4541 posts 6021 karma points MVP 3x admin c-trib
    Jun 17, 2013 @ 11:47
    Dirk De Grave
    0

    Combining 2 xpath axes

    Hi,

    Might a simple questions to those xslt gurus out there, just checking if it is possible at all. Currently having a site with quite a large number of nodes (+10k), so travelling the content tree can become quite slow using the DynamicNode/IPublishedContent extension methods Descendants()...

    Because of slow performance of these methods, I'm reverting to using plain old xslt to fetch the nodes I need to work with (XPath() is also available as extension method). Here's what nodes I'm trying to fetch:

    Content tree has following structure (not repeating top level 'Content' node)

    - Site
    -- Homepage
    --- Theme 1
    ---- Theme 1-1
    --- Theme 2
    ---- Theme 2-1
    ----- Category 2-1-1
    ------ Category 2-1-1-1

    I guess you get the point. There's a max of 2 'Theme' levels and a max of 2 'Category' levels

    Fetching nodes using xpath expression: .//*[@level > {0} and @level <= {1} and ./hideFromNavigation != '1'] takes about 450msec ({0} and {1} is replaced with level info for Theme and Category nodes). Last condition is only available on Theme/Category nodes, so we could rewrite the xpath expression to only include the last condition which improves performance significantly (Taking it down to 300msec)

    Here comes the good part. If I split up my xpath expression into several ones, not using the "//" axe, such as

    /root/Site/Home[@id={0}]/Theme[hideFromNavigation != '1'] (1 msec)
    /root/Site/Home[@id={0}]/Theme[hideFromNavigation != '1']/Theme[hideFromNavigation != '1'] (4 msec)
    /root/Site/Home[@id={0}]/Theme[hideFromNavigation != '1']/Theme[hideFromNavigation != '1']/Category[hideFromNavigation != '1'] (62 msec) and
    /root/Site/Home[@id={0}]/Theme[hideFromNavigation != '1']/Theme[hideFromNavigation != '1']/Category[hideFromNavigation != '1']/Category[hideFromNavigation != '1'] (44 msec)

    I was able to again improve performance drastically (Total = 100 msec)

    Question is:

    * Can I combine those into a single xpath expression (So I could get away with a single statement instead of 4)
    * Why would the last statement have better performance than the 3rd one (Even tho it has to query more nodes)

    Looking forward to any answers...

     

    Cheers,

    /Dirk

     

     

  • Chriztian Steinmeier 2800 posts 8790 karma points MVP 8x admin c-trib
    Jun 17, 2013 @ 12:20
    Chriztian Steinmeier
    1

    Hi Dirk,

    First off, I am sure you can optimize that by using XSLT keys - e.g. here's a previous post that was helpful in that regard.

    I'm not sure I understand what you mean by combining the 4 expressions into one? What's the final set of nodes you're looking for?

    The fact that the 4th is quicker than the 3rd - could it maybe just be that the fetched data from the 3rd is cached and reused? XSLT Processors are doing a lot of optimising, so it may also be that the fact that the path is more specific (thus eliminating more nodes from being searched) makes it perform faster...

    /Chriztian

  • Dirk De Grave 4541 posts 6021 karma points MVP 3x admin c-trib
    Jun 17, 2013 @ 13:27
    Dirk De Grave
    0

    well, i need both theme docs at level X and theme docs at level X+1 without using the "//" axis, as this hurts performance. I'm sure the "//" axis is designed to do such task, but it's much slower compared to executing 2 xpath queries against the same start node

    i don't think i can use the key stuff in c#, can i?

    /Dirk

  • Dirk De Grave 4541 posts 6021 karma points MVP 3x admin c-trib
    Jun 17, 2013 @ 13:28
    Dirk De Grave
    0

    Oh, and same goes for 'Categories' docs, which are at level X+2 and X+3 (X taken from previous post)

     

    /Dirk

  • Chriztian Steinmeier 2800 posts 8790 karma points MVP 8x admin c-trib
    Jun 17, 2013 @ 13:50
    Chriztian Steinmeier
    0

    Hi Dirk,

    Well, I guess there probably is a way to use keys in C# too - Lee Kelleher would probably know where to look, since he's done stuff including the XsltContext (?) before...

    In plain XSLT, I would at least cache the results of each, e.g:

    <xsl:variable name="rootID" select="1234" />
    
    <xsl:variable name="siteRoot" select="umbraco.library:GetXmlNodeById($rootID)" />
    
    <xsl:variable name="themes1"     select="$siteRoot/Theme[not(hideFromNavigation = 1)]" />
    <xsl:variable name="themes2"     select="$themes1/Theme[not(hideFromNavigation = 1)]" />
    <xsl:variable name="categories1" select="$themes2/Category[not(hideFromNavigation = 1)]" />
    <xsl:variable name="categories2" select="$categories1/Category[not(hideFromNavigation = 1)]" />

    Using keys, I'd index them by level since that's what you're using to retrieve them, something like:

    <xsl:key name="themesByLevel" match="Theme[not(hideFromNavigation = 1)]" use="@level" />
    <xsl:key name="categoriesByLevel" match="Category[not(hideFromNavigation = 1)]" use="@level" />
    
    <xsl:variable name="X" select="2" />
    
    <xsl:variable name="themes1"     select="key('themesByLevel', $X)" />
    <xsl:variable name="themes2"     select="key('themesByLevel', $X + 1)" />
    <xsl:variable name="categories1" select="key('categoriesByLevel', $X + 2)" />
    <xsl:variable name="categories2" select="key('categoriesByLevel', $X + 3)" />

    Hope we're getting closer to a solution for you,

    /Chriztian

     

Please Sign in or register to post replies

Write your reply to:

Draft