Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
?
Solved

Using XSL to create dynamic dropdown menus

Posted on 2003-03-07
11
Medium Priority
?
986 Views
Last Modified: 2010-05-19
I want to create a pair of nested dynamic dropdown menus from a XML doc.  I am willing to double the amount of points for this question if someone can give me a specific example of what I need.

I have two menus one for locations, and one for customers.  The second menu list values are dependant on the value of the first menu.

My idea is that once the location box is changed, it fires of some JavaScript (insert your help here) that uses Path (more help please) to get the child nodes below the id of selected location.  The JavaScript would then transform the new DOM object created from the XPath statement using XSL (help) to render the customers select box using some type of innterHtml inside a div.

The xml doc looks something like:

<sites>
     <location name="site 1" id="1">
          <customer name="cust 1" id="11">
               <host name="host 1" id="111"/>
               <host name="host 1" id="112"/>
               <host name="host n" id="11n"/>
          </customer>
          <customer name="cust n" id="1a1">
               <host name="host 1" id="11a1"/>
               <host name="host 1" id="1s12"/>
               <host name="host n" id="1s1n"/>
          </customer>
     </location>
     <location name="site n" id="n">
          <customer name="cust 1" id="11">
               <host name="host 1" id="111"/>
               <host name="host 1" id="112"/>
               <host name="host n" id="11n"/>
          </customer>
          <customer name="cust n" id="1a1">
               <host name="host 1" id="11a1"/>
               <host name="host 1" id="1s12"/>
               <host name="host n" id="1s1n"/>
          </customer>
     </location>
</sites>
0
Comment
Question by:makman111
11 Comments
 
LVL 28

Expert Comment

by:sybe
ID: 8090423
Is it for IE 5+ only ? Because then you can easy use XSL for this. I am not sure which (other) browsers support Javascript for XSL.
0
 

Author Comment

by:makman111
ID: 8090708
Yes
0
 
LVL 14

Expert Comment

by:avner
ID: 8096784
<html>
<head>
<title>about:blank</title>
<script language="javascript1.2">
<!-- copyright(c) avcoh@yahoo.com


var oXML = null;

function createSelect(obj,sIDEffected)
{
     var oTarget = document.forms['formName'].elements[sIDEffected];

     var sValue = obj.options[obj.options.selectedIndex].value;
     var oList = oXML.selectSingleNode("//location[@id='"+sValue+"']");
     if (oList)
          {
               addOptions(oTarget, oList.childNodes);
          }
}

function addOptions(oSelect, oChildNodes)
{
var iLen = oSelect.options.length;
     for (var i=0;i<iLen;i++)
          {
               oSelect.options[0] = null;
          }
var iLen = oChildNodes.length;
     for (var i=0;i<iLen;i++)
          {
               oSelect.options[oSelect.options.length]= new Option(oChildNodes[i].getAttribute("name"),oChildNodes[i].getAttribute("id"));
          }

}


function init()
{
     oXML = document.getElementById("data");

     addOptions(document.getElementById("location"), oXML.selectSingleNode("/sites").childNodes);
     document.getElementById("location").options[0].selected="true";
     document.getElementById("location").fireEvent("onchange");
     //createSelect(document.getElementById("location"),"customer", "1");
}

-->
</script>
</head>
<body onload="init()">
<form id="formName">
Location :
<select name="location" onchange="createSelect(this,'customer')">
</select><br/>

Customer:
<select name="customer">
</select>
</form>



<xml id="data">
<sites>
    <location name="site 1" id="1">
         <customer name="Customer!" id="11">
              <host name="host 1" id="111"/>
              <host name="host 1" id="112"/>
              <host name="host n" id="11n"/>
         </customer>
         <customer name="Customer!!!!" id="1a1">
              <host name="host 1" id="11a1"/>
              <host name="host 1" id="1s12"/>
              <host name="host n" id="1s1n"/>
         </customer>
    </location>
    <location name="site n" id="n">
         <customer name="cust 1" id="11">
              <host name="host 1" id="111"/>
              <host name="host 1" id="112"/>
              <host name="host n" id="11n"/>
         </customer>
         <customer name="cust n" id="1a1">
              <host name="host 1" id="11a1"/>
              <host name="host 1" id="1s12"/>
              <host name="host n" id="1s1n"/>
         </customer>
    </location>
</sites>
</xml>
</body>
</html>
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 9

Accepted Solution

by:
sparkplug earned 2000 total points
ID: 8097185
Hi,

Here's an XSLT version:

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

<!-- These are the params for specifying the locationid and customerid for the default selection in each dropdown list box-->
<xsl:param name="DefaultSelectedLocationID" select="string(/sites/location[1]/@id)" />
<xsl:param name="DefaultSelectedCustomerID" select="string(/sites/location[@id=$SelectedLocationID]/customer[1]/@id)" />

<!-- These are the variable for storing the locationid and customerid for the current selection in each dropdown list box-->
<xsl:variable name="SelectedLocationID" select="$DefaultSelectedLocationID" />
<xsl:variable name="SelectedCustomerID" select="$DefaultSelectedCustomerID" />

<xsl:template match = "/">
<html>
  <head>
  <script type = "text/javascript" language = "javascript">
      <![CDATA[
         var oXSLDoc = document.XSLDocument;
         var oXMLDoc = document.XMLDocument;
      
      //Updates XSL variable
         function updateVar(sName, sValue)
         {
              //select the xsl:variable node. This is for storing the item selected in each drop down list
              var oVarNodeSelectAttr = oXSLDoc.selectSingleNode( "//xsl:variable[@name='" + sName + "']/@select" );
            
            
            //reset to default or store the selected value
              if (sValue == '_default')
                     oVarNodeSelectAttr.nodeValue = "$Default" + sName;
            else
                    oVarNodeSelectAttr.nodeValue = "string('" + sValue + "')";

         
         }
         
         //retransform the current XML document with the current XSL document
         function reDisplay()
         {
              //we only want to transform from the root node. This is so we dont repeat the headers and script sections
             divResults.innerHTML = oXMLDoc.documentElement.transformNode( oXSLDoc );

         }
      ]]>
    </script>
    </head>
   <body>
      <div ID = "divResults">
             <!-- This is a place holder for the dropdown lists which will by replaced with the above javascript -->
         <xsl:apply-templates select="sites"/>
      </div>
   </body>
</html>

</xsl:template>

<xsl:template match = "sites">
      Location:
      <select name="LocationList" onchange="updateVar('SelectedLocationID', this.value);updateVar('SelectedCustomerID', '_default');reDisplay()">
            <xsl:apply-templates select="location">
                  <xsl:sort select="@name"/>
            </xsl:apply-templates>
      </select>
      <br/>
      <br/>
      Customer:
      <select name="CustomerList" onchange="updateVar('SelectedCustomerID', this.value);reDisplay()">
            <xsl:apply-templates select="location[@id = $SelectedLocationID]/customer">
                  <xsl:sort select="@name"/>
            </xsl:apply-templates>
      </select>

      <br/>
      <br/>
      <table border="1">
      <tr><th>host</th><th>host id</th></tr>
            <xsl:apply-templates select="location[@id = $SelectedLocationID]/customer[@id = $SelectedCustomerID]/host">
                  <xsl:sort select="@name"/>
            </xsl:apply-templates>
      </table>
 
   
</xsl:template>

<xsl:template match = "location">
      <option>
            <xsl:attribute name="value">
                 <xsl:value-of select="@id"/>
            </xsl:attribute>
            <xsl:if test="@id = $SelectedLocationID">
               <xsl:attribute name="selected">selected</xsl:attribute>
            </xsl:if>
            <xsl:value-of select="@name"/>
      </option>
</xsl:template>


<xsl:template match = "customer">
      <option>
            <xsl:attribute name="value">
                 <xsl:value-of select="@id"/>
            </xsl:attribute>
            <xsl:if test="@id = $SelectedCustomerID">
               <xsl:attribute name="selected">selected</xsl:attribute>
            </xsl:if>
            <xsl:value-of select="@name"/>
      </option>
</xsl:template>

<xsl:template match = "host">
      <tr>
            <td><xsl:value-of select="@name"/></td>
            <td><xsl:value-of select="@id"/></td>
      </tr>
</xsl:template>

</xsl:stylesheet>


Put the filename at the top of the XML to get this to work e.g. <?xml:stylesheet type="text/xsl" href="dropdown.xslt"?>

>S'Plug<
0
 

Author Comment

by:makman111
ID: 8098372
I keep geeting a javascript error.

'oXSLDoc is undefined' in the line

var oVarNodeSelectAttr = oXSLDoc.selectSingleNode( "//xsl:variable[@name='" + sName + "']/@select" );
0
 

Author Comment

by:makman111
ID: 8098919
Okay fixed the javascript (I was actually using the wrong XML doc), but It does not seem to be re-building the doc.  

>S'Plug<

Can you contact me direct via e-mail?  jmaki@makman.net
0
 
LVL 9

Expert Comment

by:sparkplug
ID: 8099264
Hi,

When you say that it is not rebuilding the doc, do you mean that the second drop down list is not being updated when the first drop down list is changed? What XML file are you using to test this? The example above contains several repeated names so the changes might not be apparent? I tested this on IE6 before posting it but not any other browser. I would expect it to work in IE5.5 but not IE5.

>S'Plug<

0
 

Author Comment

by:makman111
ID: 8099280
I think I got it figured out...   Is there any way to do this so that the customer box is rendered sperately than the locaiton box?

This way I can have two different <div> tags at different locations?
0
 

Author Comment

by:makman111
ID: 8099285
Also,

How do I make the default option "Choose One"

Thanks
0
 
LVL 9

Expert Comment

by:sparkplug
ID: 8099428
I'm not sure what you mean by seperating the two boxes. You can have two different <div>s as in the following extract. In fact you can put whatever HTML tags you like into this template. You could for example change the order or put them in a table.

<xsl:template match = "sites">
<div id="divLocation">
     Location:
     <select name="LocationList" onchange="updateVar('SelectedLocationID', this.value);updateVar('SelectedCustomerID', '_default');reDisplay()">
          <option value="-1">Choose One</option>
          <xsl:apply-templates select="location">
               <xsl:sort select="@name"/>
          </xsl:apply-templates>
     </select>
</div>

     <br/>
     <br/>

<div id="divCustomer">
     Customer:
     <select name="CustomerList" onchange="updateVar('SelectedCustomerID', this.value);reDisplay()">
          <option value="-1">Choose One</option>          <xsl:apply-templates select="location[@id = $SelectedLocationID]/customer">
               <xsl:sort select="@name"/>
          </xsl:apply-templates>
     </select>
</div>

     <br/>
     <br/>
     <table border="1">
     <tr><th>host</th><th>host id</th></tr>
          <xsl:apply-templates select="location[@id = $SelectedLocationID]/customer[@id = $SelectedCustomerID]/host">
               <xsl:sort select="@name"/>
          </xsl:apply-templates>
     </table>
 
 
</xsl:template>


To make the default option "Choose One", add "<option value="-1">Choose One</option>" to each select box as shown above. Also change the default params at the top of the file as follows:

<!-- These are the params for specifying the locationid and customerid for the default selection in each dropdown list box-->
<xsl:param name="DefaultSelectedLocationID" select="string(-1)" />
<xsl:param name="DefaultSelectedCustomerID" select="string(-1)" />

>S'Plug<
0
 
LVL 9

Expert Comment

by:sparkplug
ID: 8099446
Sorry that should be:

<option value="-1">
<xsl:if test="$SelectedLocationID = -1">
    <xsl:attribute name="selected">selected</xsl:attribute>
</xsl:if>
Choose One
</option>

e.g.

  Location:
    <select name="LocationList" onchange="updateVar('SelectedLocationID', this.value);updateVar('SelectedCustomerID', '_default');reDisplay()">
        <option value="-1">
        <xsl:if test="$SelectedLocationID = -1">
        <xsl:attribute name="selected">selected</xsl:attribute>
        </xsl:if>
         Choose One
         </option>
         <xsl:apply-templates select="location">
              <xsl:sort select="@name"/>
         </xsl:apply-templates>
    </select>


>S'Plug<
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Browsing the questions asked to the Experts of this forum, you will be amazed to see how many times people are headaching about monster regular expressions (regex) to select that specific part of some HTML or XML file they want to extract. The examp…
Many times as a report developer I've been asked to display normalized data such as three rows with values Jack, Joe, and Bob as a single comma-separated string such as 'Jack, Joe, Bob', and vice versa.  Here's how to do it. 
Despite its rising prevalence in the business world, "the cloud" is still misunderstood. Some companies still believe common misconceptions about lack of security in cloud solutions and many misuses of cloud storage options still occur every day. …
How can you see what you are working on when you want to see it while you to save a copy? Add a "Save As" icon to the Quick Access Toolbar, or QAT. That way, when you save a copy of a query, form, report, or other object you are modifying, you…
Suggested Courses

579 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question