Well, I have basically the same kind of thing using XSLT, with no 'hacking' required...
Each page is an XML file (could be XSP but doesn't have to be) which contains a number of components. Each component consists of a vocabulary of tags inside its own namespace, thus if I want navigation I have: <nav:navigation xmlns:nav="http://xml.giantelectronicbrain.com/NS/navigation" order="100" chunkid="2" style="side" id="/library/200.xml"> <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="/library/200.xml"/> </nav:navigation> (noting that the xinclude here could be replaced with literal content, but for modularities sake its best to include common content of course). Notice that the <nav:navigation/> component includes an style="side" (in this example) which later is going to let us select which XSLT template to use to render it for the particular purpose we want, in this case sidebar navigation. This lets us use the same XML data structure to represent side or top navigation, or potentially any other type we wish to make XSLT templates for. The order attribute establishes the order of the components on the output page. They could simply be output in document order, but we're building a web-based page building system and its simpler to establish the order this way. chunkid is also used by that system to build editing forms, and the ID attribute just lets us name each thing if we want, which is sometimes handy later on. Now, our pipeline basically looks like this: <FILES *.xsp> AxAddProcessor application/x-xsp . </FILES> <FILES ~ "\.(xml|xsp)$"> AxAddProcessor application/x-saxmachines . AxAddProcessor text/xsl /corexsl/lib/build_page.xsl AxAddProcessor text/xsl html.xsl </FILES> The XSP part is self-explanatory, if your page is XSP it simply does that first. We use sax-machines to translate to the user's preferred language (there's no need for XSLT for that, SAX is much faster at brute scanning the document and processing each language choice, it really doesn't have to care what the rest of the document structure is). Next is an XSLT template, build_page.xsl. Its purpose is to act as a 'first pass' at building the final output. It simply <xsl:include/>'s a bunch of stylesheets which do things like merge XSP provided derived values into forms and things like that (I will provide a forms example with this for clarity). Its other major purpose is to gather up any <err:error/> tags into a master list of errors (this is necessary because the design of XSP does not guarantee that you can place these error messages in any particular spot in the document hierarchy). Its general effect is to pass the document through as-is, but any component that wanted to have this 'first pass' can add an <xsl:include/> there to get it. Finally we have the last step. This is the one which translates the page to html. It essentially acts as a template for an HTML page and again uses a series of <xsl:include>'s, one for each component, to do translations. In the example above our html.xsl will include /components/navigation.xsl which has a template like <xsl:template match="nav:[EMAIL PROTECTED]'sidenav']> (generate html here) </xsl:template> and since everything in our page below the docroot is a component of some kind the entire page can contain something like: <xsl:apply-templates match="/page/*"> <xsl:sort select="@order" data-type="number"/> </xsl:apply-templates> and all our components come out in order. In actual practice we have found of course that HTML templates need several of these 'insertion points' in order to get things organized right, so we introduced another level of page structure. Each page contains a set of location containers, so a page might look like: <page> <maincontents> Some components here </maincontents> <leftside> Stuff to go in the left sidebar here </leftside> <footer> Stuff to go in the footer here </footer> </page> and the template then might be like <html> <head/> <body> (some structural html here, like probably the start of a table) <xsl:apply-templates match="/page/leftside/*"> <xsl:sort select="@order" data-type="number"/> </xsl:apply-templates> (some more structural html here) <xsl:apply-templates match="/page/maincontents/*"> <xsl:sort select="@order" data-type="number"/> </xsl:apply-templates> (and so on and so-forth) The nice thing about this approach is that we can also build other output formats like pdf. All I need is a stylesheet selection mechanism that lets me put "pdf.xsl" as the last thing in the chain instead of 'html.xsl" and then that just translates to pdf (perhaps using an intermediate form, so I may even add several steps, like componentstolatex.xsl and then latextopdf.xsl or whatever). Finally I've been able to merge in stuff from other formats like docbook as well, you just have to have a chain that wraps it in a component tag and use that to select stylesheet templates to include which translate to you output format. In most cases its not too hard and I was able to make docbook documents show up on my site inside my HTML template's main content area pretty easily using just the off-the-shelf docbook xslt to html stylesheets available at sourceforge. On Wednesday 26 February 2003 11:04 am, Tom Howe wrote: > Since XSLT has started winning the war against XPathScript and since I > have had to hack XPathScript to get it to do what I want, I am considering > making the move to XSLT but have to validate that I can do what I need to. > > Essentially we have a component driven site. Each part of a page is > described by a separate XML file plus there are XML files that relate to > the url that is being accessed, we call these the primary page. > > eg > we have xml files for primary pages: /home/index.xml, /home/signin.xml > etc > > and > we have xml files for components: /components/menu.xml, > /components/header.xml etc > > Any primary page xml or component xml file can "require" (by means of > <include/> tags that another component is loaded. The various component > xml files are then combined to form one long XML file that is first > processed by XSP and then by XPathScript. > > Each component that was loaded has a stylesheet attached to it and I have > hacked XPathScript to process each component with its own stylesheet. > > > so the XML document looks a bit like this... > > <?xml version="1.0" encoding="ISO-8859-1"?> > <?xml-stylesheet type="application/x-xsp" href="."? > <?xml-stylesheet type="application/x-xpathscript" > href="/stylesheets/main.xps" > ?> > <xsp:page...> > > <page> > > <home> > > <index stylesheet="home.xsp"> > .. contents of home/index.xml... > </index> > > </home> > > <components> > > <header stylesheet="header.xsp"> > .. contents of header.xml.. > </header> > > <menu stylesheet="menu.xsp"> > .. contentns of menu.xml.. > </menu> > > <footer stylesheet="footer.xsp"> > .. contentns of menu.xml.. > </footer> > > </components> > > </page> > > </xsp:page> > > > > --------- > Then after the XSP processing, XPathScript uses the main.xps file to > transform this page. The stylesheet looks like this.. > > <html> > <body> > <%= insert("/components/header"); %> > <table> > <tr> > <td> > <%= insert("/components/menu"); %> > </td> > <td> > <%= insert($AxKit::Apache::request->uri); %> > </td> > </tr> > </table> > <%= insert("/components/footer"); %> > </body> > </html> > > ----- > > The insert() method takes an XPATH as a parameter and attempts to locate > the node from the XPATH and then applies the stylesheet specified by the > stylesheet= attribute. > > The beauty of this is that the stylesheet is not "loading" components. > Everything is compiled in advance. The stylesheet simply determines where > things go and what they should look like. It also allows us to assign > stylesheets to each component of a page and keep things well structured. > > -------------- > > > My first question is, > > Is there a way to do this using XSLT? > > I've seen Barrie Slaymakers tutorial on XSP, Taglibs and Pipelines > (http://www.perl.com/pub/a/2002/04/16/axkit.html) which shows an example > pipeline where a weather report goes through 2 XSLT transformations, first > transforming the weather XML and then laying out the whole page. What > happens when you want to pull in a header.xml and footer.xml and have > them rendered by separate XSL stylesheets, ideally with the results of > individual components being cached so that only "dynamic" components of > the page are regenerated each time. > > The way I pull together the various "components" of the page is through > the use of a custom apache handler that runs prior to AxKit as part of a > Apache::Filter chain. I've thought that maybe it would be better to use an > AxKit Provider handler to do this but I cant find much info about making > Providers. > > > > Ideally it would be nice to be able to do this. > > 1) Request comes in for somefile.xml > > 2) Something decides that somefile.xml, header.xml, menu.xml, footer.xml > are all required components. > > 3) It is determined that footer.xml also requires submenu.xml. > > 4) All 5 components are processed by XSP (in a given order) and cached > where possible. > > 5) The resulting xml of the 5 components are then processed by their > individual stylesheets. (which ideally inherit from the main page's > stylesheet, in this case somefile.xml ) submenu should be transformed > and included in a nested fashion within the footer. > > The results of the 4 components are combined in 1 XML document that might > look like this... > > <?xml.. ? > <data> > > <!--various stuff about the page--> > <url></url> > <colour></colour> > > <component href="/somefile.xml" primary> > (cached) html output of somefile.xml transformed by somefile.xsl > </components> > > <component href="/header.xml> > (cached) html output of header.xml transformed by header.xsl > </component> > > <component href="/menu.xml> > (cached) html output of menu.xml transformed by menu.xsl > </component> > > <component href="/footer.xml> > (cached) html output of footer.xml transformed by footer.xsl > including the resulting output of submenu.xml transformed by submenu.xsl > </component> > > </data> > > ...................... > > 6) this final page is then transformed by a default xsl stylesheet, say > default.xsl :) which provides the common structure of the page. > > > > Can anyone offer a means of achieving this using XSLT, or an alternative > that offers the same advantages. Namely, > > * Components that can be individually defined > * Separate stylesheets for each component, which inherit from the parent > component at run time. > * Ability to drive what appears on the page from at the XSP stage (ie, if > the component is in the XML then its shown, otherwise it isnt. Not the > usual case of pulling in components from the stylesheet) > * Individual caching of components at XSP,XML and final HTML level > > > any help much appreciated, > > Tom Howe > [EMAIL PROTECTED] > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] -- Tod Harter Giant Electronic Brain --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
