Copied to clipboard

Flag this post as spam?

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


  • Ove Andersen 435 posts 1541 karma points c-trib
    Jul 09, 2009 @ 17:20
    Ove Andersen
    1

    Help with document type crawler

    Does anyone know of a way to list nodes from multiple sources?

    I have this content layout:
    Content
    |_    Website 1
           |_    News
                  |_    News 1
                  |_    News 2
    |_    Website 2
           |_    News
                  |_    News 1
                  |_    News 2

    Now, in the News template under Website 1, there is a news listing.
    I need to list all News nodes in Website 1 and Website 2 here. And it must not list any news from other websites than those two.

    If anyone know how to select all nodes with a @nodeTypeAlias that is the child of a master document type, it would also be very welcome.
    I have a master document type called News, and the I have more specific types of News as sub-documenttypes. What I need is a xslt that finds all nodes based on a common master document type.

    My current idea is to pass a comma separated list in the macro and then run a for-each for every @id there, but it is not a pretty solution.

    Is it possible to insert another xslt file in the middle of another xslt file?
    That way I might create some "wrapper" xslt files and do it recursively.

    Does anyone know of a good solution to this?

  • Chris Dunn 75 posts 127 karma points
    Jul 09, 2009 @ 17:43
    Chris Dunn
    0

    You could create a property yes/no in the document type for a news document type (grouping news doctype vs individual news items) to indicate 'include on news feed' etc.  Then in the macro, simple check for this doctypealias of the NEWS document where property = 1, then display all nodes under that?

    -Chris

  • Sjors Pals 617 posts 270 karma points
    Jul 09, 2009 @ 19:34
    Sjors Pals
    0

    You can use a XSLT Macro like this:

     <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE xsl:Stylesheet [
    <!ENTITY nbsp "&#x00A0;">
    ]>
    <xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxml="urn:schemas-microsoft-com:xslt" xmlns:umbraco.library="urn:umbraco.library"
    exclude-result-prefixes="msxml
    umbraco.library">

    <xsl:output method="xml" omit-xml-declaration="yes"/>

    <xsl:param name="currentPage"/>

    <xsl:variable name="minLevel" select="1"/>

    <xsl:template match="/">

    <xsl:for-each select="$currentPage/ancestor-or-self::root//node [@id=1078 or @id=1159][@alias = 'Prj_Links']/descendant::node">
    <xsl:value-of select="@nodeName"/><br/>
    </xsl:for-each>
    </xsl:template>
    </xsl:stylesheet></span><span class="pln"><br /></span>

  • Sjors Pals 617 posts 270 karma points
    Jul 09, 2009 @ 19:36
    Sjors Pals
    0

    Sorry pasted wrong script, this is the correct one:

     

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE xsl:Stylesheet [
      <!ENTITY nbsp "&#x00A0;">
    ]>
    <xsl:stylesheet
     version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:msxml="urn:schemas-microsoft-com:xslt" xmlns:umbraco.library="urn:umbraco.library"
    exclude-result-prefixes="msxml
    umbraco.library">

      <xsl:output method="xml" omit-xml-declaration="yes"/>

      <xsl:param name="currentPage"/>

      <xsl:variable name="minLevel" select="1"/>

      <xsl:template match="/">

        <xsl:for-each select="$currentPage/ancestor-or-self::root//node [@id=1078 or @id=1159]/descendant::node[@nodeTypeAlias= 'NewsItem']">
          <xsl:value-of select="@nodeName"/><br/>
        </xsl:for-each>
      </xsl:template>
    </xsl:stylesheet>

  • Paul Blair 466 posts 731 karma points
    Jul 09, 2009 @ 22:45
    Paul Blair
    1

    Hi,

    When i need to do this I add a SiteID property to my property types and then I can select records like this:

    select="$currentPage/ancestor::root/node[ string(data [@alias='SiteID']) = 'FairlieAgile' and string(data [@alias='umbracoNaviHide']) != '1']"

    Similar to the above solution but does not rely on hard-coding the id's so works better if you will be releasing to differernt environments.

  • Jesper Hauge 298 posts 487 karma points c-trib
    Jul 10, 2009 @ 00:24
    Jesper Hauge
    1

    I noticed this paragraph in your post:If anyone know how to select all nodes with a @nodeTypeAlias that is the child of a master document type, it would also be very welcome."</span>Let's say your News-nodes have nodeTypeAlias="News", and items below News nodes have nodeTypeAlias="NewsItem", then you should be able to select all NewsItem nodes into a variable with the following declaration, and let's say all your websites has a root node with nodeTypeAlias="Website"</span>You should then be able to "chain" your selection criteria together in a xpath statement like this:</span>

    <xsl:variable name="newsNodes"
      select="$currentPage/ancestor::root//node[@nodeName = 'Website1' or @nodeName = 
        'Website2']//node[@nodeTypeAlias='News']/node[@nodeTypeAlias='NewsItem']
    />

    The //'s in this xpath works the same way as descendant::node would.

    It's a fairly long xpath, and I haven't tested it myself, but I'm pretty sure it will work.

    I also noticed you mentioned id it's  possible to "<span style="white-space: pre-wrap;">insert another xslt file in the middle of another xslt file?". Not sure exactly what you mean by that, and I don't know how well you know xslt. But if your main exposure to xslt has been through Umbraco xslt examples you will se a lot of <xsl:for-each /> statements, which generally leads to fairly convoluted xslt code.</span>In other parts of xslt-land the use of multiple xslt templates in one xslt file is much more common, and your statement above plus the idea of "wrapper" xslt made me think that this maybe was what you're looking for. Let's say you'd want all your news-items rendered in a particular way; then you could do it like this (not using xsl:for-each):</span>

    <!-- Start of xsl file here -->
    
    <xsl:param name="currentPage" />
    <xsl:variable name="newsNodes" select="** See code above **" />
    
    <xsl:template match="/">
      <ul>
        <xsl:apply-templates select="$newsNodes" />
      </ul> 
    </xsl:template">
    
    <xsl:template match="node">
      <li>
        <h2><a href="{umbraco.library:NiceUrl(@id)}"><xsl:value-of select="data[@alias='header']" /></a><h2>
        <p><xsl:value-of select="data[@alias='resume']</p>
      </li>
    </xsl:template>
    
    <!-- End of xsl file here -->

    I think that the limited use of multiple xsl:template in Umbraco-land may have something to do with every node in the xml-file we're working on is a <node />, because in more normal xml the nodes will have different names eg. <News><NewsItem></NewsItem><NewsItem></NewsItem></News>, and you then have different templates that are used for nodes with different names, where everything is a <node /> in Umbraco. But actually xsl templates can be coerced into only reacting on a certain condition using the mode-attribute.

    <xsl:apply-templates select="** Some select statement that selects nodes **" mode="newsItem" />
    
    <xsl:template match="node" mode="newsItem">
    
    </xsl:template>

    Regards
    .Hauge

  • Ove Andersen 435 posts 1541 karma points c-trib
    Jul 10, 2009 @ 13:41
    Ove Andersen
    0

    After some thought about your advices, I think I'm going to try to make a wrapper that can take on a comma-separated list of node id's.
    It will then make a node-set with all the subnodes under the list of nodes.

    After this, it will redirec t to a template with the node-set as a parameter, and this template will take care of iterating through the node-set.

    Current code:

    <xsl:param name="source" select="/macro/source"/>
    <xsl:variable name="SourceXML">
    <xsl:choose>
    <xsl:when test="string($source)!=''">
    <xsl:for-each select="umbraco.library:Split($source, ',') /value">
    <xsl:value-of select="umbraco.library:GetXmlNodeById(.)"/>
    </xsl:for-each>   
    </xsl:when>
    </xsl:choose>
    </xsl:variable>

    Now, testing on the web page with the following code inside the "/" template:

    <p><xsl:copy-of select="$source"/></p>
    <ul>
    <xsl:for-each select="msxsl:node-set($SourceXML)/node">
    <li><xsl:value-of select="./@nodeName"/></li>
    </xsl:for-each>
    &nbsp;
    </ul>   
    <p><xsl:copy-of select="msxsl:node-set($SourceXML)"/></p>

    Both paragraphs return the expected result as you can see here.
    The list however, returns nothing.

    Does anyone have a clue why I don't get a list of nodenames using this code?

  • Sjors Pals 617 posts 270 karma points
    Jul 10, 2009 @ 14:04
    Sjors Pals
    0

    I really don't see why you want to do it like this, you ask for a solution for a problem, the solutions provided are working and are general considered as good practice, you are trying to make from a simple problem a very complex one, why on earth would you like to redirect as you want to render a submenu?

  • Ove Andersen 435 posts 1541 karma points c-trib
    Jul 10, 2009 @ 14:19
    Ove Andersen
    0

    I don't want to render a submenu. What I need is a reusable "wrapper" like the on posted by Jesper Hauge, that I can use in several xslt files. It would have been no problem hard-coding the thing, but I don't want a new xslt file for every new situation.

    Reusable code is worth spending time to figure out, as it will save time later.

    I could go for Paul Blair's solution, but if it is possible do this by supplying a comma-separated list if id's, then it will be a better solution for me.

     

  • Sjors Pals 617 posts 270 karma points
    Jul 10, 2009 @ 14:28
    Sjors Pals
    1

    Sorry for the misunderstanding, is it maybe an idea to use the input from a multipage picker?

     I did use that to create a related links? Still not sure or that's what you want, it's a little bit confusing for me ;)

     

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE xsl:Stylesheet [
        <!ENTITY nbsp "&#x00A0;">
    ]>
    <xsl:stylesheet
        version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:msxml="urn:schemas-microsoft-com:xslt"
        xmlns:umbraco.library="urn:umbraco.library"
        exclude-result-prefixes="msxml umbraco.library">


        <xsl:output method="xml" omit-xml-declaration="yes"/>

        <xsl:param name="currentPage"/>

        <xsl:template match="/">
            <xsl:variable name="mcpNodeSet" select="umbraco.library:Split($currentPage/node/data [@alias = 'LC_Links'][1], ',')" />
            <xsl:if test="string-length($currentPage/node/data[@alias = 'LC_Links'][1]) != 0">
                <div class="link-box">
                    <h2>Quick links</h2>
                    <ul>

                        <!-- //link-box -->

                        <xsl:for-each select="$mcpNodeSet/value">
                            <xsl:variable name="currentItem" select="umbraco.library:GetXmlNodeById(current()/text())"/>
                            <li>
                                <a href="{umbraco.library:NiceUrl(current()/text())}">
                                    <xsl:value-of select="$currentItem/@nodeName"/>
                                </a>
                            </li>
                        </xsl:for-each>

                    </ul>
                </div>
            </xsl:if>
        </xsl:template>

    </xsl:stylesheet>

  • Ove Andersen 435 posts 1541 karma points c-trib
    Jul 10, 2009 @ 14:32
    Ove Andersen
    0

    Hmm. That looks almost exactly what I need!

    Thank you! I'm gonna try this out right now and post back with the results.

  • Ove Andersen 435 posts 1541 karma points c-trib
    Jul 10, 2009 @ 15:40
    Ove Andersen
    0

    It seems the my main problem is that when using a "value-of" in a variable, the variable becomes a string, not a node-set.

    That is why I am not able to iterate through the $SourceXML and get the nodes from it.

    Does anyone know how to fix this?

  • Ove Andersen 435 posts 1541 karma points c-trib
    Jul 13, 2009 @ 13:58
    Ove Andersen
    0

    I have found the solution!

    The error is caused by the <xsl:value-of /> in the variable $SourceXML.

    It seems that when you use <xsl:value-of /> in a <xsl:variable>, the data is saved as a string.

    The solution was to use <xsl:copy-of /> and then make a new variable that encased $SourceXML in a msxsl:node-set.<xsl:variable name="SourceXML">
    <xsl:for-each select="umbraco.library:Split($source, ',') /value">
    <xsl:copy-of select="umbraco.library:GetXmlNodeById(current()/text())"/>
    </xsl:for-each>    
    </xsl:variable>

    I have blogged about the problem here.

    Now I have a collection of nodes that I can operate on. Thank you for the help everyone!

  • Sjors Pals 617 posts 270 karma points
    Jul 13, 2009 @ 15:17
    Sjors Pals
    0

    Hi Ove was wondering or you got this working...

Please Sign in or register to post replies

Write your reply to:

Draft