I've created an organisation tree representation in the content, so as an example I have nodes of:
Group Compliance
Head of Group Compliance
Department 1
Employee 1
Employee 2
Department 2
Employee 1
Department 3
I need to get a nested XML output to feed into a organistion chart component, so this would look along the lines of:
<item id="123" name="Head of Group Compliance">
<item id="124" name="Department 1">
<item id="125" name="Employee 1"></item>
<item id="125" name="Employee 2"></item>
</item>
<item id="126" name="Department 2">
<item id="127" name="Employee 1"></item>
<item id="128" name="Employee 2"></item>
</item>
<item id="129" name="Department 3">
</item>
</item>
I can't seem to get the nesting of the XML nodes to work correctly, Department 2 nests into Department 1 and Department 3 nests into Department 2 whereas they should be on the same level.
Looks like you might have done so but the SiteMap.xslt that comes out the box with Umbraco should be able to achieve what you need without much tweaking?
Yes the xslt is based on the SiteMap and if I was using the 'ul' and 'li' tags it looks OK, however if I ditch the 'ul' tags and swap out the 'li' tags for the xml 'item' tags then the nesting is not correct ?
Thanks very much for your help, I managed to get to the bottom of it, as you've indicated and I had thought all along it looks like it should work, eventually figured out that you need to change the xsl output method to 'html' instead of the default 'xml', not sure why that makes it work though, hopefully someone can explain.
This thread is years old, but if anyone else comes across this post I ran into a similar problem and produced the same kind of erroneous code as shown above. My problem was (and it might be here too) that the xPath in my select statement didn't give me access to the nodes I wanted it to because I wasn't looking for them in the right level of hierarchy. Take a look at your for-each statement:
<xsl:for-each select="$parent/child::*[@isDoc and string(umbracoNaviHide) != '1']">
You may need to change that xPath to get to your nodes. Hope this helps someone.
Org Chart
I've created an organisation tree representation in the content, so as an example I have nodes of:
Group Compliance
Head of Group Compliance
Department 1
Employee 1
Employee 2
Department 2
Employee 1
Department 3
I need to get a nested XML output to feed into a organistion chart component, so this would look along the lines of:
<item id="123" name="Head of Group Compliance">
<item id="124" name="Department 1">
<item id="125" name="Employee 1"></item>
<item id="125" name="Employee 2"></item>
</item>
<item id="126" name="Department 2">
<item id="127" name="Employee 1"></item>
<item id="128" name="Employee 2"></item>
</item>
<item id="129" name="Department 3">
</item>
<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp " "> ]>
<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" xmlns:Exslt.ExsltCommon="urn:Exslt.ExsltCommon" xmlns:Exslt.ExsltDatesAndTimes="urn:Exslt.ExsltDatesAndTimes" xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath" xmlns:Exslt.ExsltRegularExpressions="urn:Exslt.ExsltRegularExpressions" xmlns:Exslt.ExsltStrings="urn:Exslt.ExsltStrings" xmlns:Exslt.ExsltSets="urn:Exslt.ExsltSets"
exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets ">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:param name="currentPage"/>
<xsl:variable name="source" select="1372"/>
<xsl:template match="/">
<xsl:call-template name="drawNodes">
<xsl:with-param name="parent" select="umbraco.library:GetXmlNodeById($source)/self::* [@isDoc]"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="drawNodes">
<xsl:param name="parent"/>
<xsl:for-each select="$parent/child::*[@isDoc and string(umbracoNaviHide) != '1']">
<item id="{@id}" name="{@nodeName}">
<xsl:if test="count($parent/child::* [@isDoc and string(umbracoNaviHide) != '1']) > 0">
<xsl:call-template name="drawNodes">
<xsl:with-param name="parent" select="."/>
</xsl:call-template>
</xsl:if>
</item>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Hey Mike,
Looks like you might have done so but the SiteMap.xslt that comes out the box with Umbraco should be able to achieve what you need without much tweaking?
Rich
Hi Rich,
Yes the xslt is based on the SiteMap and if I was using the 'ul' and 'li' tags it looks OK, however if I ditch the 'ul' tags and swap out the 'li' tags for the xml 'item' tags then the nesting is not correct ?
Cheers,
Mike
Hey Mike,
Can you post a pic of your Content Tree and also the html produced (or maybe the a snippet)?
Rich
Hi Rich,
Thanks for yur help, the node structure is as described in my original post, here's a sample of the XML output:
<?xml version="1.0" encoding="UTF-8"?>
<item id="" name="Head of Group Compliance">
<item id="" name="Department 1">
<item id="" name="Employee 1">
<item id="" name="Employee 2"></item>
<item id="" name="Department 2">
<item id="" name="Employee 1">
<item id="" name="Employee 2"></item>
<item id="" name="Department 3"></item>
<item id="" name="Department 1">
<item id="" name="Employee 1">
<item id="" name="Employee 2"></item>
<item id="" name="Employee 1">
<item id="" name="Employee 2">
<item id="" name="Department 2">
<item id="" name="Employee 1">
<item id="" name="Employee 2"></item>
<item id="" name="Employee 1">
<item id="" name="Employee 2">
<item id="" name="Department 3"></item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
Mike
Hey Mike,
I'm not sure why you've made the changes that you have from the original site map xslt?
I'm guessin its this line that's causing the problem
<xsl:for-each select="$parent/child::*[@isDoc and string(umbracoNaviHide) != '1']">
What does this get you?
<!-- update this variable on how deep your site map should be --><xsl:variable name="maxLevelForSitemap" select="4"/> <xsl:template match="/"><div id="sitemap"> <xsl:call-template name="drawNodes"> <xsl:with-param name="parent" select="umbraco.library:GetXmlNodeById(1372)"/> </xsl:call-template></div></xsl:template> <xsl:template name="drawNodes"><xsl:param name="parent"/> <xsl:if test="umbraco.library:IsProtected($parent/@id, $parent/@path) = 0 or (umbraco.library:IsProtected($parent/@id, $parent/@path) = 1 and umbraco.library:IsLoggedOn() = 1)"><ul><xsl:for-each select="$parent/* [@isDoc and string(umbracoNaviHide) != '1' and @level <= $maxLevelForSitemap]"> <li> <a href="{umbraco.library:NiceUrl(@id)}"><xsl:value-of select="@nodeName"/></a> <xsl:if test="count(./* [@isDoc and string(umbracoNaviHide) != '1' and @level <= $maxLevelForSitemap]) > 0"> <xsl:call-template name="drawNodes"> <xsl:with-param name="parent" select="."/> </xsl:call-template> </xsl:if> </li></xsl:for-each></ul></xsl:if></xsl:template>Rich
Hi Rich,
I've just tried that but it still nests the departments
<item id="1399" name="Head of Group Compliance">
<item id="1400" name="Department 1">
<item id="1403" name="Employee 1">
<item id="1404" name="Employee 2">item>
<item id="1401" name="Department 2">
<item id="1405" name="Employee 1">
<item id="1406" name="Employee 2">item>
<item id="1402" name="Department 3">item>
item>
item>
item>
item>
item>
Here's a screen grab of the node structure:
Cheers,
Mike
Hey Mike,
Very strange indeed.
However that cannot be the output from the code I posted as my posted code was writing out anchor links.
Would be good to see your content tree as well (I know you say it's structured as in post 1 but would be good incase something else is going on)
Rich
Sorry, cross post, I couldn't see your content structure before!
Still be interested to see the actual output of my code posted above.
We'll get there!
Rich
Hi Rich,
Here's the output of your XSLT:
Head of Group Compliance
Hey Mike,
That looks like what you need right, departments and Employees all look correct.
So you just need to edit this xslt to produce your xml (unless I'm mistaken)
Rich
Hi Rich,
I've modified the xslt as follows, and included the output below it.
<!-- update this variable on how deep your site map should be -->
<xsl:variable name="maxLevelForSitemap" select="6"/>
<xsl:template match="/">
<div id="sitemap">
<xsl:call-template name="drawNodes">
<xsl:with-param name="parent" select="umbraco.library:GetXmlNodeById(1398)"/>
</xsl:call-template>
</div>
</xsl:template>
<xsl:template name="drawNodes">
<xsl:param name="parent"/>
<xsl:if test="umbraco.library:IsProtected($parent/@id, $parent/@path) = 0 or (umbraco.library:IsProtected($parent/@id, $parent/@path) = 1 and umbraco.library:IsLoggedOn() = 1)">
<item id="{@id}" name="{@nodeName}">
<xsl:for-each select="$parent/* [@isDoc and string(umbracoNaviHide) != '1' and @level <= $maxLevelForSitemap]">
<item id="{@id}" name="{@nodeName}">
<xsl:if test="count(./* [@isDoc and string(umbracoNaviHide) != '1' and @level <= $maxLevelForSitemap]) > 0">
<xsl:call-template name="drawNodes">
<xsl:with-param name="parent" select="."/>
</xsl:call-template>
</xsl:if>
</item>
</xsl:for-each>
</item>
</xsl:if>
</xsl:template>
Output:
<?xml version="1.0" encoding="UTF-8"?>
<div id="sitemap">
<item id="" name="">
<item id="1399" name="Head of Group Compliance">
<item id="1399" name="Head of Group Compliance">
<item id="1400" name="Department 1">
<item id="1400" name="Department 1">
<item id="1403" name="Employee 1">
<item id="1404" name="Employee 2"></item>
</item>
<item id="1401" name="Department 2">
<item id="1401" name="Department 2">
<item id="1405" name="Employee 1">
<item id="1406" name="Employee 2"></item>
</item>
<item id="1402" name="Department 3"></item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</div>
Cheers,
Mike
Hey Mike,
Your code has an error as you've added an another item within the loop.
Try this
<!-- update this variable on how deep your site map should be --><xsl:variable name="maxLevelForSitemap" select="4"/> <xsl:template match="/"><div id="sitemap"> <xsl:call-template name="drawNodes"> <xsl:with-param name="parent" select="umbraco.library:GetXmlNodeById(1372)"/> </xsl:call-template></div></xsl:template> <xsl:template name="drawNodes"><xsl:param name="parent"/> <xsl:if test="umbraco.library:IsProtected($parent/@id, $parent/@path) = 0 or (umbraco.library:IsProtected($parent/@id, $parent/@path) = 1 and umbraco.library:IsLoggedOn() = 1)"><xsl:for-each select="$parent/* [@isDoc and string(umbracoNaviHide) != '1' and @level <= $maxLevelForSitemap]"> <item> <a href="{umbraco.library:NiceUrl(@id)}"><xsl:value-of select="@nodeName"/></a> <xsl:if test="count(./* [@isDoc and string(umbracoNaviHide) != '1' and @level <= $maxLevelForSitemap]) > 0"> <xsl:call-template name="drawNodes"> <xsl:with-param name="parent" select="."/> </xsl:call-template> </xsl:if> </item></xsl:for-each> </xsl:if></xsl:template> RichHi Rich,
This is the output I get using your modified xslt:
<?xml version="1.0" encoding="UTF-8"?>
<div id="sitemap">
<item id="1399" name="Head of Group Compliance">
<item id="1400" name="Department 1">
<item id="1403" name="Employee 1">
<item id="1404" name="Employee 2"></item>
<item id="1401" name="Department 2">
<item id="1405" name="Employee 1">
<item id="1406" name="Employee 2"></item>
<item id="1402" name="Department 3"></item>
</item>
</item>
</item>
</item>
</item>
</div>
Cheers,
Mike
Hi Rich,
Thanks very much for your help, I managed to get to the bottom of it, as you've indicated and I had thought all along it looks like it should work, eventually figured out that you need to change the xsl output method to 'html' instead of the default 'xml', not sure why that makes it work though, hopefully someone can explain.
Default is:
<xsl:output method="xml" omit-xml-declaration="yes"/>
Changed to:
<xsl:output method="html" omit-xml-declaration="yes"/>
Cheers,
Mike
Hey Mike,
Glad you got it sorted :)
Rich
This thread is years old, but if anyone else comes across this post I ran into a similar problem and produced the same kind of erroneous code as shown above. My problem was (and it might be here too) that the xPath in my select statement didn't give me access to the nodes I wanted it to because I wasn't looking for them in the right level of hierarchy. Take a look at your for-each statement:
<xsl:for-each select="$parent/child::*[@isDoc and string(umbracoNaviHide) != '1']">
You may need to change that xPath to get to your nodes. Hope this helps someone.
is working on a reply...