Search

Does anyone know how the navigation works for getsymphony.com? I'm specifically talking about having one bar with high level navigation (Explore, Download, Learn, Discuss, Get Involved, Get Support) and a separate bar with sub level navigation (dependent on the high level, but if your looking at this it's probably Forum, Blog, Issues, Twitter). I'm assuming getsymphony.com actually uses Symphony CMS. If that's not the case, does anyone know how to get something like that working with an extension or XSLT file?

I'm trying to accomplish the same thing on my website but haven't been able to figure it out. Also, Multilevel Navigation and Recursive Navigation don't quite seem to work without significant rewriting. I haven't found other extensions or XSLT files that appear to get close to that kind of menu.

In addition, I expect to have several pages that are handled the way the Symphony Tutorials are handled where each page will maintain the navigation from above, but will also include a unique contents bar.

Would you mind posting your XML for us to see what you are working with?

Actually, those utilities should work right out of the box if you're supplying the right structure: All those menu items are in fact Pages, fetched with the builtin Navigation datasource. The utilities simply select the right one to use depending on the location of your user in the page-tree.

I can also confirm that this is how getsymphony.com is doing it.

@phoque - I might not be asking the right question or understanding how those utilities work. Symphony is very new to me and I have very little experience with XSLT. Right now, my site is pretty simple. I've followed the tutorials to create a navigation data source (the built-in one) that is connected to all the pages. I also have a master.xsl utility that, for now, just has the basic site outline and is included in each page. It's in the master.xsl file that I'm trying to incorporate the two navigation bars - either via the existing utilities or by writing my own.

@bzerangue - Right now, master.xsl looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml"
    doctype-public="-W3CDTD XHTML 1.0 Strict//EN"
    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
    omit-xml-declaration="yes"
    encoding="UTF-8"
    indent="yes" />

<xsl:include href="navigator.xsl" />

<xsl:template match="/">
    <html>
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
            <meta http-equiv="Content-Language" content="en-us" />
            <title>Site Title</title>
            <link href="{$workspace}/styles/main.css" rel="stylesheet" type="text/css" />
        </head>

        <body>
            <div id="container">

                <div id="header">
                    <div id="logo">
                        <a href="/"><img src="{$workspace}/images/logo-header.png" alt="Safeware Logo" /></a>
                    </div>
                    <div id="main-navigation">
                        <ul>
                            <xsl:apply-templates select="data/navigation">
                            </xsl:apply-templates>
                        </ul>
                    </div>
                    <div id="sub-navigation">
                        <ul>
                            <xsl:apply-templates select="data/navigation">
                            </xsl:apply-templates>
                        </ul>
                    </div>
                </div>

                <div id="content">
                    <xsl:apply-templates />
                </div>

                <div id="footer">
                    <div id="footer-navigation">
                        <ul>
                            <xsl:apply-templates select="data/navigation">
                            </xsl:apply-templates>
                        </ul>
                    </div>
                    <p>Address</p>
                    <p>Copyright &#169; 2012</p>
                </div>

            </div>
        </body>
    </html>
</xsl:template>

</xsl:stylesheet>

I've tried to work from the XSL in both Recursive Navigation and Multilevel Navigation, but can't seem to get parameters correct.

I've gotten closest with Recursive Navigation by placing:

<div id="main-navigation">
  <ul>
    <xsl:apply-templates select="data/navigation/page" mode="navigation">
      <xsl:with-param name="levels" select="0" />
      <xsl:with-param name="root-url" select="$root" />
    </xsl:apply-templates>
  </ul>
</div>

<div id="sub-navigation">
  <ul>
    <xsl:apply-templates select="data/navigation/page[@handle=$current-page]/page" mode="navigation">
      <xsl:with-param name="levels" select="0" />
      <xsl:with-param name="root-url" select="$current-url" />
    </xsl:apply-templates>
  </ul>
</div>

into the main-navigation and sub-navigation divs, respectively. That gives a permanent "main menu" that is static and a "sub menu" that depends on the main menu. Unfortunately, the sub menu disappears if I navigate too deep. I want the main menu always to reflect level 0, and the sub menu always to reflect level 1 but still depend on what is selected at level 0.

Thanks for the help, and sorry if I'm missing something obvious. Like I said, I'm pretty new to this.

You could use the $root-page parameter in the sub-navigation instead of the $current-page parameter.

@klaftertief - Sorry. I copied the wrong code. It Should be:

<div id="main-navigation">
  <ul>
    <xsl:apply-templates select="data/navigation/page" mode="navigation">
      <xsl:with-param name="levels" select="0" />
      <xsl:with-param name="root-url" select="$root" />
    </xsl:apply-templates>
  </ul>
</div>

<div id="sub-navigation">
  <ul>
    <xsl:apply-templates select="data/navigation/page[@handle=$current-page]/page" mode="navigation">
      <xsl:with-param name="levels" select="0" />
      <xsl:with-param name="root-url" select="$current-url" />
    </xsl:apply-templates>
  </ul>
</div>

I've corrected the code above as well. But if I use $root for the sub menu, the links don't work. Instead of:

/my.domain/level-0/level-1

The link would be:

/my.domain/level-1

Even so, I would still have the problem of the sub menu disappearing if I navigate past level 1, and that solution won't leave the page's parents (or grandparents) highlighted so that users know where they are in the navigation tree. It looks to me like the Multilevel Navigation is supposed to maintain a chain of links labeled "active" but I haven't been able to get that concept incorporated into the menus the way I'm using them, and it would still leave the disappearing menu problem when I navigate past level 1.

Both utilities are doing it a bit differently: they nest the submenu within the main menu:

<xsl:apply-templates select="data/navigation" mode="navigation">
  <xsl:with-param name="levels" select="2" />
</xsl:apply-templates>

should do it in that case (you'd need to change your CSS to style the menu correctly).

If you wanted to keep your structure though I'd say the following should work:

<div id="main-navigation">
  <ul>
    <xsl:apply-templates select="data/navigation/page" mode="navigation">
      <xsl:with-param name="levels" select="0" />
      <xsl:with-param name="root-url" select="$root" />
    </xsl:apply-templates>
  </ul>
</div>

<div id="sub-navigation">
  <ul>
    <xsl:apply-templates select="data/navigation/page/descendant-or-self::page[@id = $current-id]" mode="navigation">
      <xsl:with-param name="levels" select="0" />
      <xsl:with-param name="root-url" select="$current-url" />
    </xsl:apply-templates>
  </ul>
</div>

The important thing is the descendant-or-self axis: It matches any page within the current node or the node itself: So any menu item in the current second level item may be active to trigger this rule.

Also I am making use of @id = $current-id instead of @handle = $current-page as handles aren't necessary unique.

Please note that those examples aren't tested but only made up in my mind. Even if it doesn't work, those should be right cues to get you started. :-)

Thanks for all the help, everyone. It looks like I have a lot more to learn about using XSL. I thought there would be a more robust/reusable way of doing it, but I've basically settled on buidling each navigation menu individually. For anyone interested, this is what I ended up using in my navigator.xsl file:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<!-- Create unordered list depending on mode -->
<xsl:template match="navigation" mode="main">
  <ul>
    <xsl:apply-templates select="page" mode="main">
    </xsl:apply-templates>
  </ul>
</xsl:template>

<xsl:template match="navigation" mode="sub">
  <ul>
    <xsl:apply-templates select="page/page" mode="sub">
    </xsl:apply-templates>
  </ul>
</xsl:template>

<!-- Add list items and links depending on mode -->
<xsl:template match="page" mode="main">
  <xsl:if test="not(types/type = 'hidden') and not(types/type = 'admin')">
    <li>
      <a href="{$root}/{@handle}/">
        <xsl:if test="descendant-or-self::node()[@id = $current-page-id]">
          <xsl:attribute name="class">current</xsl:attribute>
        </xsl:if>
        <xsl:value-of select="name"/>
      </a>
    </li>
  </xsl:if>
</xsl:template>

<xsl:template match="page" mode="sub">
  <xsl:if test="not(types/type = 'hidden') and not(types/type = 'admin')">
    <xsl:if test="parent::node()/descendant-or-self::node()[@id = $current-page-id]">
      <li>
        <a>
          <xsl:attribute name="href">
            <xsl:value-of select="concat($root, '/', ../@handle, '/', @handle)"/>
          </xsl:attribute>
          <xsl:if test="descendant-or-self::node()[@id = $current-page-id]">
            <xsl:attribute name="class">current</xsl:attribute>
          </xsl:if>
          <xsl:value-of select="name"/>
        </a>
      </li>
    </xsl:if>
  </xsl:if>
</xsl:template>

</xsl:stylesheet>

It works for now since the site is set up so that users only need to navigate around in levels 0 and 1.

I have one last question though. In the section at the bottom for:

<xsl:template match="page" mode="sub">

Why do I have to use:

<xsl:value-of select="concat($root, '/', ../@handle, '/', @handle)"/>

Rather than something like:

<xsl:value-of select="concat($root, '/', parent/@handle, '/', @handle)"/>

.. is a shorthand for parent::node(). parent itself would actually select a childnode named parent.

Create an account or sign in to comment.

Symphony • Open Source XSLT CMS

Server Requirements

  • PHP 5.3-5.6 or 7.0-7.3
  • PHP's LibXML module, with the XSLT extension enabled (--with-xsl)
  • MySQL 5.5 or above
  • An Apache or Litespeed webserver
  • Apache's mod_rewrite module or equivalent

Compatible Hosts

Sign in

Login details