We help IT Professionals succeed at work.
Get Started

How to select nested node

980 Views
Last Modified: 2013-11-18
I'm very new at this and trying to make a change to an existing xslt file. The XML has nested <Item> and <Menu> nodes that pretty much follow this pattern (two levels of <Menu>)

<Menu>
   <Item>
   <Item>
       <Menu>
           <Item>
           <Item>
   <item>
 
I only want the top level <Menu> node and everything below it if it is selected.

This almost gets me there:
<xsl:apply-templates select="Menu[descendant-or-self::MenuSelected='true']  "/>

The problem then is that I'm not seeing the second-level <Menu> node and its <Item> nodes.

So I tried:
<xsl:apply-templates select="Menu[descendant-or-self::MenuSelected='true']  |  Menu[ancestor-or-self::MenuSelected='true'] "/>

But that made no difference.
I cannot for the life of me figure out how to get that second-level <Menu> when the first-level is selected.

Following is the xslt file. The statement referenced above is at line 64.
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:output method="xml" indent="yes"/>
	<!--xsl:strip-space elements="*"/-->
	<xsl:variable name="controlHash"><xsl:value-of select="/MenuDataResult/Info/ControlIdHash"/></xsl:variable>
	<xsl:variable name="menuConst"><xsl:value-of select="$controlHash"/>_<xsl:value-of select="/MenuDataResult/Info/ControlMenuId"/>_</xsl:variable>
	<xsl:variable name="masterHash"><xsl:value-of select="/MenuDataResult/Info/MasterControlIdHash"/></xsl:variable>
	<xsl:variable name="buttonNoScriptLink"><xsl:value-of select="/MenuDataResult/Info/ButtonNoScriptLink"/></xsl:variable>
	<xsl:variable name="slaveMenu"><xsl:value-of select="/MenuDataResult/Info/IsSlaveControl"/></xsl:variable>
	<xsl:variable name="startLevel"><xsl:value-of select="/MenuDataResult/Info/StartLevel"/></xsl:variable>



    <xsl:template match="/">
        <xsl:copy-of select="."/>
        <xsl:apply-templates select="MenuDataResult/Item"/>
    </xsl:template>

    <!-- First level <Item> node - there is only one; everything else is contained in it -->
    <!-- So this is linking in the css and setting up the div's and their classes -->
	<xsl:template match="Item[parent::MenuDataResult]">
		<xsl:choose>
			<xsl:when test="/MenuDataResult/Info/MenuFragment='false'">
				<xsl:if test="/MenuDataResult/Info/UseCssHardLink='true'">
				<link type="text/css" rel="stylesheet">
					<xsl:attribute name="href"><xsl:value-of select="/MenuDataResult/Info/CssFileName"/></xsl:attribute>
				</link>
				</xsl:if>

				<div>
					<xsl:attribute name="class"><xsl:value-of select="/MenuDataResult/Info/WrappingClassName"/></xsl:attribute>
					<div>
						<xsl:attribute name="class">ekflexmenu</xsl:attribute>
						<xsl:attribute name="id"><xsl:value-of select="$menuConst"/>0_ekflexmenu</xsl:attribute>
						<xsl:if test="/MenuDataResult/Info/EnableMouseOverPopUp = 'true'">
							<xsl:attribute name="onmouseover">return (ekFlexMenuPopupMsIn(event));</xsl:attribute>
							<xsl:attribute name="onmouseout">return (ekFlexMenuPopupMsOut(event));</xsl:attribute>
						</xsl:if>
						<div>
							<xsl:attribute name="class">ekflexmenu_menu_level_0<xsl:text xml:space="preserve"> </xsl:text>ekflexmenu_submenu</xsl:attribute>
							<ul>
								<xsl:attribute name="class">ekflexmenu_submenu_items</xsl:attribute>
								<xsl:attribute name="id"><xsl:value-of select="$menuConst"/>0_submenu_items</xsl:attribute>
								<xsl:apply-templates select="Item"/>
							</ul>
						</div>
					</div>
				</div>
				<xsl:call-template name="addJavascript"/>
			</xsl:when>
			<xsl:otherwise>
				<xsl:apply-templates select="Item"/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>

    <!-- (<Item> node that contains a <Menu> node) OR (<Item> node that has ItemType of Submenu) -->
	<xsl:template match="Item[child::Menu | ItemType='Submenu']">
		<li>
			<xsl:attribute name="class">ekflexmenu_menu_level_<xsl:value-of select="ItemLevel"/><xsl:text xml:space="preserve"> </xsl:text>ekflexmenu_submenu<xsl:if test="(number(ItemLevel) = number($startLevel))"><xsl:text xml:space="preserve"> </xsl:text>ekflexmenu_startlevel</xsl:if></xsl:attribute>
			<xsl:attribute name="id"><xsl:value-of select="./Menu/MenuIdString"/></xsl:attribute>
			<!-- <xsl:apply-templates select="Menu"/> -->
			<xsl:apply-templates 
			select="Menu[descendant-or-self::MenuSelected='true']"/>
		</li>
	</xsl:template>

    <!-- Any <Menu> node -->
   <xsl:template name="makelist" match="Menu"> 
        <xsl:call-template name="makeButton" />
		<xsl:if test="./Item/Menu[MenuId!=''] | ./Item[ItemId!=''][ItemType!='Submenu'] ">
			<ul>
				<xsl:attribute name="id"><xsl:value-of select="MenuIdString"/>_submenu_items</xsl:attribute>
				<xsl:choose>
					<xsl:when test="MenuSelected='true' and /MenuDataResult/Info/EnableSmartOpen='true'">
						<xsl:attribute name="class">ekflexmenu_submenu_items</xsl:attribute>
					</xsl:when>
					<xsl:when test="ChildMenuSelected='true' and /MenuDataResult/Info/EnableSmartOpen='true'">
						<xsl:attribute name="class">ekflexmenu_submenu_items</xsl:attribute>
					</xsl:when>
					<xsl:otherwise>
						<xsl:choose>
							<xsl:when test="/MenuDataResult/Info/StartCollapsed='true'">
						<xsl:attribute name="class">ekflexmenu_submenu_items_hidden</xsl:attribute>
							</xsl:when>
							<xsl:otherwise>
								<xsl:attribute name="class">ekflexmenu_submenu_items</xsl:attribute>
					</xsl:otherwise>
						</xsl:choose>
					</xsl:otherwise>
				</xsl:choose>
				<xsl:apply-templates select="Item"/>
			</ul>
		</xsl:if>
	</xsl:template>

    <!-- Any <Item> node whose ItemType is not Submenu -->
	<xsl:template match="Item[ItemType!='Submenu']">
		<li>
			<xsl:variable name="targetLoc">
				<xsl:choose>
					<xsl:when test="ItemTarget='1'">_blank</xsl:when>
					<xsl:when test="ItemTarget='3'">_parent</xsl:when>
					<xsl:when test="ItemTarget='4'">_top</xsl:when>
					<xsl:otherwise>_self</xsl:otherwise>
				</xsl:choose>
			</xsl:variable>

			<a>
				<xsl:choose>
					<xsl:when test="ItemSelected='true'">
						<xsl:attribute name="class">ekflexmenu_link_selected</xsl:attribute>
					</xsl:when>
					<xsl:otherwise>
				<xsl:attribute name="class">ekflexmenu_link</xsl:attribute>
					</xsl:otherwise>
				</xsl:choose>
				<xsl:choose>
					<xsl:when test="ItemType='Javascript'">
						<xsl:attribute name="onclick">
							Javascript:<xsl:value-of select="ItemLink"/>;return false;
						</xsl:attribute>
						<xsl:attribute name="href">#NoScroll</xsl:attribute>
					</xsl:when>
					<xsl:otherwise>
						<xsl:choose>
							<xsl:when test="not(ItemLink='')">
								<xsl:attribute name="href">
									<xsl:value-of select="ItemLink"/>
								</xsl:attribute>
							</xsl:when>
							<xsl:otherwise>
								<xsl:attribute name="href">#NoScroll</xsl:attribute>
							</xsl:otherwise>
						</xsl:choose>
					</xsl:otherwise>
				</xsl:choose>
				<xsl:attribute name="target">
					<xsl:value-of select="$targetLoc"/>
				</xsl:attribute>
				<xsl:if test="not(ItemImage='')">
					<img>
						<xsl:attribute name="border">0</xsl:attribute>
						<xsl:attribute name="src">
							<xsl:value-of select="ItemImage"/>
						</xsl:attribute>
					</img>
				</xsl:if>
				<xsl:if test="not(ItemImageOverride='true')">
					<xsl:text> </xsl:text>
					<xsl:value-of select="ItemTitle"/>
				</xsl:if>
			</a>
			<xsl:apply-templates select="Item|Menu"/>
        </li>
	</xsl:template>

    <!-- Applies to any node that matches the if test -->
    <!-- In our case, $slave is always False; MenuFragment is always False; 
        MenuLevel=1 for top-level menus (Cost Savings, HR, Marketing, etc)
        MenuLevel=2 for any submenus below those
        So this applies whenever all three conditions are NOT met, which in our case is always 
        This template is called by the "Makelist" template that only applies to <Menu> nodes 
        So bottom line is that this is used on all of our <Menu> nodes -->
	<xsl:template name="makeButton">
		<xsl:if test="not((/MenuDataResult/Info/MenuFragment='true') and (MenuLevel = '1') and $slaveMenu='true')">
			<a>
				<xsl:attribute name="id"><xsl:value-of select="MenuIdString"/>_button</xsl:attribute>
				<xsl:attribute name="tabindex">0</xsl:attribute>
				<xsl:attribute name="onkeydown">return (ekFlexMenuKey(event));</xsl:attribute>
				<xsl:attribute name="onblur">return (ekFlexMenuMsOut(event));</xsl:attribute>
				<xsl:attribute name="onfocus">return (ekFlexMenuMsOvr(event));</xsl:attribute>
				<xsl:attribute name="onclick">return (ekFlexMenuClk(event));</xsl:attribute>
				<xsl:attribute name="onmouseover">return (ekFlexMenuMsOvr(event));</xsl:attribute>
				<xsl:attribute name="onmouseout">return (ekFlexMenuMsOut(event));</xsl:attribute>
				<xsl:choose>
					<xsl:when test="MenuSelected='true'">
						<xsl:attribute name="class">ekflexmenu_button_selected</xsl:attribute>
					</xsl:when>
					<xsl:when test="ChildMenuSelected='true'">
						<xsl:attribute name="class">ekflexmenu_button_selected</xsl:attribute>
					</xsl:when>
					<xsl:otherwise>
						<xsl:attribute name="class">ekflexmenu_button</xsl:attribute>
					</xsl:otherwise>
				</xsl:choose>
					<xsl:choose>
					<xsl:when test="Link=''">
						<xsl:attribute name="href"><xsl:value-of select="$buttonNoScriptLink"/><xsl:value-of select="MenuIdString"/></xsl:attribute>
					</xsl:when>
					<xsl:otherwise>
						<xsl:attribute name="href">
							<xsl:value-of select="Link"/>
						</xsl:attribute>
					</xsl:otherwise>
				</xsl:choose>

				<xsl:if test="not(Image='')">
					<img>
						<xsl:attribute name="border">0</xsl:attribute>
						<xsl:attribute name="src">
							<xsl:value-of select="Image"/>
						</xsl:attribute>
					</img>
				</xsl:if>
				<xsl:if test="not(ImageOverride='true')">
					<xsl:value-of select="Title"/>
				</xsl:if>
			</a>
        </xsl:if>
		<input type="hidden">
			<xsl:attribute name="id"><xsl:value-of select="MenuIdString"/>_parentid</xsl:attribute>
			<xsl:choose>
				<xsl:when test="$slaveMenu='true' and (MenuLevel = '1')">
					<xsl:attribute name="value"><xsl:value-of select="$masterHash"/>_<xsl:value-of select="/MenuDataResult/Info/ControlMenuId"/>_<xsl:value-of select="ParentId"/></xsl:attribute>
				</xsl:when>
				<xsl:otherwise>
					<xsl:attribute name="value"><xsl:value-of select="$menuConst"/><xsl:value-of select="ParentId"/></xsl:attribute>
				</xsl:otherwise>
			</xsl:choose>
		</input>
	</xsl:template>

	<xsl:template name="addJavascript">
		<script language="JavaScript" type="text/javascript">
			// Pass server control properties, etc., to Javascript:
			if (("undefined" == typeof window.ekFlexMenu_ekflexmenuArray)
				|| (null == window.ekFlexMenu_ekflexmenuArray)) {
				window.ekFlexMenu_ekflexmenuArray = new Array;
			}
			window.ekFlexMenu_ekflexmenuArray[window.ekFlexMenu_ekflexmenuArray.length] = "<xsl:value-of select="$menuConst"/>0";
			//
			if (("undefined" == typeof window.ekFlexMenu_swRev)
			|| (null == window.ekFlexMenu_swRev)) {
			window.ekFlexMenu_swRev = new Array;
			}
			window.ekFlexMenu_swRev["<xsl:value-of select="/MenuDataResult/Info/ControlIdHash"/>"] = "<xsl:value-of select="/MenuDataResult/Info/SWRevision"/>";
			//
			if (("undefined" == typeof window.ekFlexMenu_startupSubmenuBranchId)
			|| (null == window.ekFlexMenu_startupSubmenuBranchId)) {
			window.ekFlexMenu_startupSubmenuBranchId = new Array;
			}
			window.ekFlexMenu_startupSubmenuBranchId["<xsl:value-of select="/MenuDataResult/Info/ControlIdHash"/>"] = "";
			//
			if (("undefined" == typeof window.ekFlexMenu_autoCollapseBranches)
			|| (null == window.ekFlexMenu_autoCollapseBranches)) {
			window.ekFlexMenu_autoCollapseBranches = new Array;
			}
			window.ekFlexMenu_autoCollapseBranches["<xsl:value-of select="/MenuDataResult/Info/ControlIdHash"/>"] = "<xsl:value-of select="/MenuDataResult/Info/AutoCollapseBranches"/>";
			//
			if (("undefined" == typeof window.ekFlexMenu_startCollapsed)
			|| (null == window.ekFlexMenu_startCollapsed)) {
			window.ekFlexMenu_startCollapsed = new Array;
			}
			window.ekFlexMenu_startCollapsed["<xsl:value-of select="/MenuDataResult/Info/ControlIdHash"/>"] = "<xsl:value-of select="/MenuDataResult/Info/StartCollapsed"/>";
			//
			if (("undefined" == typeof window.ekFlexMenu_startWithRootFolderCollapsed)
				|| (null == window.ekFlexMenu_startWithRootFolderCollapsed)) {
				window.ekFlexMenu_startWithRootFolderCollapsed = new Array;
			}
			window.ekFlexMenu_startWithRootFolderCollapsed["<xsl:value-of select="/MenuDataResult/Info/ControlIdHash"/>"] = "false";
			//
			if (("undefined" == typeof window.ekFlexMenu_masterControlIdHash)
				|| (null == window.ekFlexMenu_masterControlIdHash)) {
				window.ekFlexMenu_masterControlIdHash = new Array;
			}
			window.ekFlexMenu_masterControlIdHash["<xsl:value-of select="/MenuDataResult/Info/ControlIdHash"/>"] = "<xsl:value-of select="/MenuDataResult/Info/MasterControlIdHash"/>";
			<xsl:if test="not($masterHash = '')">
				//
				if (("undefined" == typeof window.ekFlexMenu_subscriberList)
				|| (null == window.ekFlexMenu_subscriberList)) {
				window.ekFlexMenu_subscriberList = new Array;
				}
				if ("undefined" == typeof window.ekFlexMenu_subscriberList["<xsl:value-of select="/MenuDataResult/Info/MasterControlIdHash"/>"]) {
				window.ekFlexMenu_subscriberList["<xsl:value-of select="/MenuDataResult/Info/MasterControlIdHash"/>"] = "<xsl:value-of select="/MenuDataResult/Info/ControlIdHash"/>";
				}
				else {
				window.ekFlexMenu_subscriberList["<xsl:value-of select="/MenuDataResult/Info/MasterControlIdHash"/>"] += ",<xsl:value-of select="/MenuDataResult/Info/ControlIdHash"/>";
				}
			</xsl:if>
			//
			if (("undefined" == typeof window.ekFlexMenu_ajaxEnabled)
			|| (null == window.ekFlexMenu_ajaxEnabled)) {
			window.ekFlexMenu_ajaxEnabled = new Array;
			}
			window.ekFlexMenu_ajaxEnabled["<xsl:value-of select="/MenuDataResult/Info/ControlIdHash"/>"] = "<xsl:value-of select="/MenuDataResult/Info/AjaxEnabled"/>";
			//
			if (("undefined" == typeof window.ekFlexMenu_ajaxWSPath)
			|| (null == window.ekFlexMenu_ajaxWSPath)) {
			window.ekFlexMenu_ajaxWSPath = new Array;
			}
			window.ekFlexMenu_ajaxWSPath["<xsl:value-of select="/MenuDataResult/Info/ControlIdHash"/>"] = "<xsl:value-of select="/MenuDataResult/Info/AppPath"/>webservices/";
			// 
			if (("undefined" == typeof window.ekFlexMenu_displayXslt)
			|| (null == window.ekFlexMenu_displayXslt)) {
			window.ekFlexMenu_displayXslt = new Array;
			}
			window.ekFlexMenu_displayXslt["<xsl:value-of select="/MenuDataResult/Info/ControlIdHash"/>"] = "<xsl:value-of select="/MenuDataResult/Info/XslFileName"/>";
			//
			if (("undefined" == typeof window.ekFlexMenu_cacheInterval)
			|| (null == window.ekFlexMenu_cacheInterval)) {
			window.ekFlexMenu_cacheInterval = new Array;
			}
			window.ekFlexMenu_cacheInterval["<xsl:value-of select="/MenuDataResult/Info/ControlIdHash"/>"] = "<xsl:value-of select="/MenuDataResult/Info/CacheInterval"/>";
			//
			//////////////////////////////////////////////////////////////////
			// Add event handler calling functions:
			//   Test to ensure that ekFlexMenu is valid/reachable (this is needed 
			//   to prevent intermittent Javascript errors that can occur if user
			//   causes event to fire while page is being torn down (i.e. a link is
			//   clicked, browser is fetching new page, movement causes mouse-out...):
			function ekFlexMenu_IsValid(obj) {
				return (("undefined" != typeof obj) <xsl:text disable-output-escaping="yes">&amp;&amp;</xsl:text> (null != obj));
			}
			function ekFlexMenuPopupMsIn(event) {
				if (ekFlexMenu_IsValid(ekFlexMenu) <xsl:text disable-output-escaping="yes">&amp;&amp;</xsl:text> ekFlexMenu_IsValid(ekFlexMenu.mouseIn)) {
					return (ekFlexMenu.mouseIn(event));
				}
				return (true);
			}
			function ekFlexMenuPopupMsOut(event) {
				if (ekFlexMenu_IsValid(ekFlexMenu) <xsl:text disable-output-escaping="yes">&amp;&amp;</xsl:text> ekFlexMenu_IsValid(ekFlexMenu.mouseOut)) {
					return (ekFlexMenu.mouseOut(event));
				}
				return (true);
			}
			function ekFlexMenuKey(event) {
				if (ekFlexMenu_IsValid(ekFlexMenu) <xsl:text disable-output-escaping="yes">&amp;&amp;</xsl:text> ekFlexMenu_IsValid(ekFlexMenu.menuBtnKeyHdlr)) {
					return (ekFlexMenu.menuBtnKeyHdlr(event));
				}
				return (true);
			}
			function ekFlexMenuMsOut(event) {
				if (ekFlexMenu_IsValid(ekFlexMenu) <xsl:text disable-output-escaping="yes">&amp;&amp;</xsl:text> ekFlexMenu_IsValid(ekFlexMenu.menuBtnMouseOutHdlr)) {
					return (ekFlexMenu.menuBtnMouseOutHdlr(event));
				}
				return (true);
			}
			function ekFlexMenuMsOvr(event) {
				if (ekFlexMenu_IsValid(ekFlexMenu) <xsl:text disable-output-escaping="yes">&amp;&amp;</xsl:text> ekFlexMenu_IsValid(ekFlexMenu.menuBtnMouseOverHdlr)) {
					return (ekFlexMenu.menuBtnMouseOverHdlr(event));
				}
				return (true);
			}
			function ekFlexMenuClk(event) {
				if (ekFlexMenu_IsValid(ekFlexMenu) <xsl:text disable-output-escaping="yes">&amp;&amp;</xsl:text> ekFlexMenu_IsValid(ekFlexMenu.menuBtnClickHdlr)) {
					return (ekFlexMenu.menuBtnClickHdlr(event));
				}
				return (true);
			}
		</script>
		<xsl:if test="/MenuDataResult/Info/UseJavascriptHardLink='true'">
		<script language="javascript" type="text/javascript">
			<xsl:attribute name="src"><xsl:value-of select="/MenuDataResult/Info/AppPath"/>java/ek_flexmenu.js</xsl:attribute>
		</script>
		</xsl:if>
	</xsl:template>
</xsl:stylesheet>

Open in new window

Comment
Watch Question
Information Architect
CERTIFIED EXPERT
Top Expert 2006
Commented:
This problem has been solved!
Unlock 2 Answers and 11 Comments.
See Answers
Why Experts Exchange?

Experts Exchange always has the answer, or at the least points me in the correct direction! It is like having another employee that is extremely experienced.

Jim Murphy
Programmer at Smart IT Solutions

When asked, what has been your best career decision?

Deciding to stick with EE.

Mohamed Asif
Technical Department Head

Being involved with EE helped me to grow personally and professionally.

Carl Webster
CTP, Sr Infrastructure Consultant
Ask ANY Question

Connect with Certified Experts to gain insight and support on specific technology challenges including:

  • Troubleshooting
  • Research
  • Professional Opinions
Did You Know?

We've partnered with two important charities to provide clean water and computer science education to those who need it most. READ MORE