![]() |
XML Navigation Bar
The data for the navigation bar on this site is stored in an XML file. The advantage to this is that structure changes can be made quickly, simply by changing a few lines in the file. The basic structure of this file is:
Node (i.e., navigation bar label)
Label (text display)
Link (target URL)
Item (zero or more items for the drop-down list)
Label (text display)
Link (target URL)
Subitem (zero or more items for the pop-out list)
Label (text display)
Link (target URL)
The current contents of the navigation bar can be seen here.
The minimum needed to accomplish this is the XML file itself. However, I also decided to add a style template and schema validation file. The style template allows for a more user-friendly look to the display, and the schema validation allows a program such as Microsoft's free XML Notepad to warn file editors when they're making structural errors in the file.
In addition, to actually process this XML file as a navigation bar, two additional programming pieces are needed. In my functions.php file, I have a segment of code that processes the XML file; in navbar.css, I have style sheet statements that display the navbar elements appropriately.
XML data file
The XML file itself is fairly straightforward. Here is a portion:
<?xml version="1.0" encoding="iso-8859-1"?>
<?xml-stylesheet type="text/xsl" href="navbar.xsl"?>
<nodes xsi:noNamespaceSchemaLocation="navbar.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<node>
<label>Home</label>
<link>index.php</link>
<item>
<label>About this site</label>
<link>programming/about.php</link>
</item>
<item>
<label>Links</label>
<link>links/</link>
</item>
</node>
<node>
<label>Programming</label>
<link>programming/</link>
<item>
<label>PHP</label>
<link>programming/php/survey/</link>
<subitem>
<label>Research survey</label>
<link>programming/php/survey/</link>
</subitem>
</item>
...
</node>
...
</nodes>
The first lines contain information about the styles and schema. These three lines:
<?xml version="1.0" encoding="iso-8859-1"?> <?xml-stylesheet type="text/xsl" href="navbar.xsl"?> <nodes xsi:noNamespaceSchemaLocation="navbar.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
could be replaced with these two:
<?xml version="1.0"?> <nodes>
The first line contains character encoding information, which is technically not needed in this particular case. The second line (<?xml-stylesheet type="text/xsl" href="navbar.xsl"?>) links to the style sheet, navbar.xsl. The third line includes code (xsi:noNamespaceSchemaLocation="navbar.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance") which links to the schema, navbar.xsd, as well as containing a standard reference to W3's standard schema namespace.
The structure of the rest of the file follows structural limitations described above, formalized in the xsd file.
XSD schema file
The schema file formalizes the structure shown above. Because this is a fairly simple structure with no attributes, the XSD is likewise fairly simple, containing two basic type definitions, one for a parent element (nodes, node, item, and subitem) and one for a text-containing element (link, label). The schema file starts as below:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name='item'>
<xs:complexType>
<xs:sequence>
<xs:element ref='label'/>
<xs:element ref='link'/>
<xs:element ref='subitem' minOccurs='0' maxOccurs='unbounded'/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name='label'>
<xs:complexType mixed='true'>
</xs:complexType>
</xs:element>
...
</xs:schema>
In other words:
The rest of the schema file contains parallel structures for the other elements.
XSL stylesheet file
The stylesheet presents the content of the XML file in a more user-friendly format. Officially, the XSL file is an XML file, containing a portion in XHTML. Because it does not restrict the XML file, it can be modified with great flexibility after the XML and XSD files have been created. Here are the contents of the XSL file:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<p style="font:16pt Corbel; margin:1">Navigation Bar</p>
<p style="padding-left:0.25in; margin:0; font:14pt Corbel italic">Node label:
<span style="font-weight:bold; font-family:Consolas">link</span></p>
<p style="padding-left:0.5in; margin:0; font:12pt Corbel">Item label:
<span style="font-weight:bold; font-family:Consolas">link</span></p>
<p style="padding-left:0.75in; margin:0; font:10pt Corbel">Subitem label:
<span style="font-weight:bold; font-family:Consolas">link</span></p>
<xsl:for-each select="nodes/node">
<p style="padding-left:0.25in; margin:1; font:14pt Corbel">
<xsl:value-of select="label"/>:
<span style="font-weight:bold; font-family:Consolas"><xsl:value-of select="link" /></span>
</p>
<xsl:for-each select="item">
<p style="padding-left:0.5in; margin:0.5; font:12pt Corbel">
<xsl:value-of select="label"/>:
<span style="font-weight:bold; font-family:Consolas"><xsl:value-of select="link" /></span>
</p>
<xsl:for-each select="subitem">
<p style="padding-left:0.75in; margin:0; font:10pt Corbel">
<xsl:value-of select="label"/>:
<span style="font-weight:bold; font-family:Consolas"><xsl:value-of select="link" /></span>
</p>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
The wrapper lines--the top three and bottom two--are standard template lines for the XML schema specification. The remaining lines are XHTML except for specific lines referring back to the XML structure. The two types of XML-content commands contained in this snippet are:
PHP function
In order to process this XML file for use in the header of the website pages, there is a module in the functions file included on most pages on this site. The relevant code (simplified for the sake of example) is:
$xml = simplexml_load_file($uppath."template/navbar.xml");
foreach ($xml->node as $node) {
$popuptext = "";
if (count($node->item)>0) {
$popuptext = ' class="popup"';
}
echo '<li><a href="'.$node->link.'"'.$popuptext.'>'.$node->label.'</a>';
if (count($node->item)>0) {
echo '<ul class="drop">';
foreach ($node->item as $item) {
$popuptext = "";
if (count($item->subitem)>0) {
$popuptext = ' class="subpopup"';
}
echo '<li><a href="'.$item->link.'"'.$popuptext.'>'.$item->label.'</a>';
if (count($item->subitem)>0) {
echo '<ul class="drop">';
foreach ($item->subitem as $subitem) {
echo '<li><a href="'.$subitem->link.'">'.$subitem->label.'</a></li>';
}
echo "</ul>";
}
echo "</li>";
}
echo "</ul>";
}
echo '</li>';
}
Note that this uses SimpleXML, which was implemented in PHP5. PHP4 allows XML processing, but with quite a bit more programming.
Navbar style sheet
The final file involved in the navbar is the style sheet, which uses margins and visibility to mimic standard drop-down menu functionality. I modified a drop-down style sheet found in various places online; see the Son of Suckerfish site for an explanation of the details.