Copied to clipboard

Flag this post as spam?

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


  • Giorgos Grispos 145 posts 179 karma points
    Mar 21, 2013 @ 18:23
    Giorgos Grispos
    0

    Preceding sibling for unique nodes

    Hello,

    I need to get only unique nodes one by one. Having the following piece I am getting more than a sinlge node every time I use it, if I try to put position() = 1 or [1] at the end then I always get just the first. Any ideas?

    <xsl:copy-of select="$currentPage/descendant::*[@isDoc] /* [name() = $documentTypeAlias and @parentID = 1067 and string(nodeShowOnHome) = 1 and not(@id = preceding-sibling::Project/@id)]"/>

    Thanks, Giorgos

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Mar 21, 2013 @ 22:06
    Chriztian Steinmeier
    0

    Hi Giorgos,

    I don't fully understand what you're trying to do — could you maybe share a little more info?

    The last predicate - "and not(@id = preceding-sibling::Project/@id)" does not make sense to me - ID's are unique, so you can never have a node which has the same @id as another. Are you by any chance looping through a set of nodes, copying specific nodes into a variable? I guess that's where you could run into this...

    Another problem is that these axes (preceding::, preceding-sibling:: etc.) *always* work in "document order", so you can't use them to test against the nodes you've previously copied, if that's what you're doing.

    Let us know a little more of why you need to copy these nodes, and I'm sure we can help.

    If you're able to select all the nodes you need in a single select="...", you don't need to worry about duplicates, because a node can only exist once in a set (using copy-of destroys that), even if you select multiple "almost identical" sets, e.g.:

    <!-- Even though the first will include all the nodes in the second, only one of each will exist in the $nodes variable  -->
    <xsl:variable name="nodes" select="$currentPage//*[@isDoc] | $currentPage/*[@isDoc]" />

     

    /Chriztian

     

  • Giorgos Grispos 145 posts 179 karma points
    Mar 22, 2013 @ 08:51
    Giorgos Grispos
    0

    Hi Chriztian,

    That was a completely wrong approach from my site, you're right I was trying to loop and copy specific nodes into specific position of a cusotm xml. The idea is that I got two different node groups one with videos (@parentID=1066) and one with photos (@parentID=1067). I wanted to make a custom xml with videos and in random position add a photo and then again anag again.

    Here is the correct approach. Any other ideas are welcome.

    Cheers, Giorgos

    <xsl:variable name="nodes">
    <root>
          <xsl:for-each select="$currentPage/ancestor::root//* [@isDoc] /* [name() = $documentTypeAlias and @parentID = 1066 and string(nodeShowOnHome) = 1]">
            <xsl:copy-of select="."/>
            <xsl:if test="position() mod $RandomPhoto=0">
       <xsl:variable name="index" select="number(position() div $RandomPhoto)"/>
              <xsl:copy-of select="$currentPage/descendant::*[@isDoc] /* [name() = $documentTypeAlias and @parentID = 1067 and string(nodeShowOnHome) = 1][$index]"/>
            </xsl:if>            
          </xsl:for-each>
        </root>
      </xsl:variable>

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Mar 22, 2013 @ 09:21
    Chriztian Steinmeier
    100

    Hi Giorgos,

    Great - that makes sense! Usually when doing something like that, I just create a "pointer" node in the collection variable, which I can then use to find the original node — that way the processor won't have to copy the full subtree etc. — here's my approach to it; feel free to ask away about it:

    <!-- Grab the container nodes -->
    <xsl:variable name="videoRoot" select="umbraco.library:GetXmlNodeById(1066)" />
    <xsl:variable name="photoRoot" select="umbraco.library:GetXmlNodeById(1067)" />
    
    <!-- Grab the relevant children -->
    <xsl:variable name="videos" select="$videoRoot/*[name() = $documentTypeAlias][nodeShowOnHome = 1]" />
    <xsl:variable name="photos" select="$photoRoot/*[name() = $documentTypeAlias][nodeShowOnHome = 1]" />
    
    <!-- Build a custom set of pointers -->
    <xsl:variable name="nodesProxy">
        <root>
            <xsl:for-each select="$videos">
                <!-- Store a reference to the video node -->
                <videoRef id="{@id}" />
                <xsl:if test="position() mod $RandomPhoto = 0">
                    <xsl:variable name="index" select="position() div $RandomPhoto" />
                    <!-- Store a reference to the photo node -->
                    <photoRef id="{$photos[$index]/@id}" />
                </xsl:if>
            </xsl:for-each>
        </root>
    </xsl:variable>
    <xsl:variable name="nodes" select="msxml:node-set($nodesProxy)/root/*" />
    
    <xsl:template match="/">
        <div>
            <!-- Process the videoRef + photoRef nodes -->
            <xsl:apply-templates select="$nodes" />
        </div>
    </xsl:template>
    
    <xsl:template match="videoRef | photoRef">
        <!-- Find the real node (it must be in the combined set of videos and photos, since that is where we took it from) -->
        <xsl:variable name="node" select="($videos | $photos)[@id = current()/@id]" />
        <p>
            <!-- Output stuff from the node -->
            <xsl:value-of select="$node/@nodeName" />
        </p>
    </xsl:template>
    

    /Chriztian 

  • Giorgos Grispos 145 posts 179 karma points
    Mar 22, 2013 @ 09:26
    Giorgos Grispos
    0

    That's great approach, so do you think that can be fatser, right?

    Thanks Chritzian!

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Mar 22, 2013 @ 09:57
    Chriztian Steinmeier
    0

    Oh yes, I think it is :-)

    Just doing the "container" variables will greatly improve the performance of the lookups, because you're no longer going up & down the tree in every iteration.

    Not copying entire nodes is guaranteed to speed things up — if not, beer's on me :-)

    /Chriztian

Please Sign in or register to post replies

Write your reply to:

Draft