Jump to content

Using document() with relative paths


boen_robot
 Share

Recommended Posts

Hello. I have a main XSLT which includes another one for the menu. The data for the menu is in it's own XML file. That said, I need to use the document() function in order to transform the menu data and still transform the main data. So far, so good. But for some reason the function isn't working as I though it would.The important part of the main XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:include href="navigation.xsl"/><xsl:template match="/">...<div id="left"><xsl:call-template name="navigation"/></div>...</xsl:template></xsl:stylesheet>

Where navigation.xsl is

<?xml version="1.0" encoding="windows-1251"?><!-- DWXMLSource="navigation.xml" --><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:variable name="Nav" select="'navigation.xml'"/><xsl:template name="navigation"><xsl:for-each select="document($Nav,/)"><xsl:call-template name="menu" /></xsl:for-each></xsl:template><xsl:template name="menu"><xsl:for-each select="document($Nav,menu)"><ul>    <xsl:for-each select="document($Nav,item)">    <li>    <a href="{document($Nav,link)}">        <xsl:value-of select="document($Nav,menu/item/title)"/>    </a>    </li>    <xsl:if test="document($Nav,menu)">        <xsl:call-template select="menu"/>    </xsl:if>    </xsl:for-each></ul></xsl:for-each></xsl:template></xsl:stylesheet>

And the problematic XML for which I need the document function.

<?xml version="1.0" encoding="windows-1251"?><menu>    <item>        <title>Home</title>        <link>#</link>    </item>    <item>        <title>Products</title>        <link>#</link>        <menu>        <!-- Contains other items with a title, link and possibly other nested menu -->        </menu>    </item></menu>

The reason I'm having a template navigation to call the second template menu is that menu is suppose to be repeated for every nested menu.The problem is that for some reason, every document() function below

<xsl:for-each select="document($Nav,menu)">

is treated as a relative path to the root of the document, not the previously selected by this for-each path (in this case- menu). It gets worse. Because of call-template which selects itself and because the root <menu> would always exist in the whole file, the template is being looped infinetly, thus eventually causing IE to crash. At the same time, FF is being wise enough to not actually select anything below

<xsl:for-each select="document($Nav,menu)">

My desired output is something like this:

<ul>    <li>        <a href="#>Home</a>    </li>    <li>        <a href="#">Products</title>        <ul>        <!-- Contains other "li"s with an "a" with attribute "href", and possibly other nested "ul" -->        </ul>    </li></ul>

Any ideas?P.S. I can't believe I'm having theese issues. In moments like this I really hope I'm not the only person here interested in XSLT.

Link to comment
Share on other sites

This is just an idea but do you think since the template 'menu' is being called with a document tree from an external document that you no longer need to reference that document and you only need to provide relative uri's as though the document were referencing it as it's own stylesheet?e.g.

<?xml version="1.0" encoding="windows-1251"?><!-- DWXMLSource="navigation.xml" --><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:variable name="Nav" select="'navigation.xml'"/><xsl:template name="navigation"><xsl:for-each select="document($Nav,/)"><xsl:call-template name="menu" /></xsl:for-each></xsl:template><xsl:template name="menu"><xsl:for-each select="menu">.........</xsl:for-each></xsl:template></xsl:stylesheet>

Link to comment
Share on other sites

Hm, no. That would result in an empty node set, because it would mean processing the main document. Or if I must say it with words:For each root element in the document $Nav, which happens to be navigation.xml in the same folder, call the template called "menu" which would do something for each "menu" found in the current position of the main document, and that position happens to be the root of the main document (see the template calling navigation).

Link to comment
Share on other sites

It almost works for me. The links are generated fine and the content shows but for some reason the <ul> and/or <li>s are not created, thus leaving all the links "floating". Here's the new code after your suggested alterations:

<?xml version="1.0" encoding="windows-1251"?><!-- DWXMLSource="navigation.xml" --><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:variable name="Nav" select="'navigation.xml'"/><xsl:template name="navigation">	<xsl:for-each select="document($Nav)/menu">  <xsl:call-template name="menu" />	</xsl:for-each></xsl:template><xsl:template name="menu" match="menu">	<ul>  <xsl:for-each select="item"> 	 <li>    <a href="{link}">   	 <xsl:value-of select="title"/>    </a>    <xsl:if test="menu">   	 <xsl:apply-templates select="menu"/>    </xsl:if> 	 </li>  </xsl:for-each>	</ul></xsl:template></xsl:stylesheet>

And my main XSLT's source could be seen here.This odd behaviour starts when call-template is first used. Manually creating links in lists gives proper results when inserted after <xsl:call-template name="navigation"/> but when inserted in the templates navigation or menu, it gives the same odd results. Cold Fusion's parser gives errors. Any clue on what I might have done wrong?

Link to comment
Share on other sites

Just a thought but you should make sure your pages by themselves are valid xml. By that I mean the .xml and the appropriate schema or dtd file parse correctly.I'm not sure what else besides that I'll have to take a look a little later

Link to comment
Share on other sites

  • 2 weeks later...

I know I'm being pretty noobish for asking this, but could you please re-post the code you made earlier, only this time as a

 in your post for later examination. Scince I last checked, you've started developing your code, making it even harder for me to try and figure out what I have done wrong. I'm thinking of copy&paste your example and edit from it on, to see where it all goes wrong (that's what I should have done from the start, only I just realized that), but I would prefer to do this with the most simple example possible. I'm trying to reach a new skill level here after all :) .
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...