Wrox Programmer Forums
Go Back   Wrox Programmer Forums > XML > XSLT
|
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old February 18th, 2009, 05:12 PM
Authorized User
 
Join Date: Feb 2009
Posts: 14
Thanks: 0
Thanked 0 Times in 0 Posts
Default Applying Templates Based on Attributes

Hi Everyone,

I'm trying to produce a document where some chapters should be layed out in portrait view and some should be layed out in landscape view. I chose to handle this by adding a "layout" attribute to the chapter element. The problem I'm running into is that when I do my xsl:apply-templates I'm still matching every chapter. What I came up with is to use named templates (shown below), but this produces every chapter in both portrait and landscape layout. I tried using modes, but it would only produce the first mode listed. I'm sure my problem is the <xsl:apply-templates/>, but I don't know how to tell it to just do chapters with a certain layout.

I left in the XSL-FO elements below for context.

Any help would be appreciated.

Thanks,
Josh

Code:
<fo:page-sequence master-reference="portrait">
Code:
<fo:flow flow-name="xsl-region-body">
<xsl:call-template name="chap-portrait"/>
</fo:flow>
</fo:page-sequence>
 
<fo:page-sequence master-reference="landscape">
<fo:flow flow-name="xsl-region-body">
<xsl:call-template name="chap-landscape"/>
</fo:flow>
</fo:page-sequence>
 
<xsl:template match="chapter[@layout='portrait']" name="chap-portrait">
<fo:block>
<xsl:apply-templates/>
</fo:block>
</xsl:template>
 
<xsl:template match="chapter[@layout='landscape']" name="chap-landscape">
<fo:block>
<xsl:apply-templates/>
</fo:block>
</xsl:template>
 
Old February 19th, 2009, 02:45 AM
Friend of Wrox
 
Join Date: Jun 2008
Posts: 291
Thanks: 9
Thanked 29 Times in 29 Posts
Thumbs up

I don't know xsl:fo. But with general idea I'm posting this.
Try mode attribute usage.

Code:
 
<fo:page-sequence master-reference="portrait">
<fo:flow flow-name="xsl-region-body">
<xsl:apply-templates select="chapter" mode="port"></xsl:apply-templates>
</fo:flow>
</fo:page-sequence>
 
<fo:page-sequence master-reference="landscape">
<fo:flow flow-name="xsl-region-body">
<xsl:apply-templates select="chapter" mode="land"></xsl:apply-templates>
</fo:flow>
</fo:page-sequence>
 
<xsl:template match="chapter[@layout='portrait']" mode="port">
<fo:block>
<xsl:apply-templates/>
</fo:block>
</xsl:template>
 
<xsl:template match="chapter[@layout='landscape']" mode="land">
<fo:block>
<xsl:apply-templates/>
</fo:block>
</xsl:template>
__________________
Rummy
 
Old February 19th, 2009, 01:51 PM
Authorized User
 
Join Date: Feb 2009
Posts: 14
Thanks: 0
Thanked 0 Times in 0 Posts
Default Applying Templates Based on Attributes

Hi Rummy,

Thanks for your reply. I already tried exactly what you've posted. Seems like it should work, but for some reason it only parses the first template listed (in this case, portrait). It behaves as if the second template isn't even there.

I might just have to resort to making two kinds of chapter elements, one for portrait <chapP> and one for landscape <chapL>, though I don't like this solution, and it doesn't seem like I should have to do it that way.

Oh well, back to the drawing board.

Thanks,
Josh

Last edited by JoshC; February 19th, 2009 at 01:55 PM..
 
Old February 19th, 2009, 11:55 PM
Friend of Wrox
 
Join Date: Jun 2008
Posts: 291
Thanks: 9
Thanked 29 Times in 29 Posts
Thumbs up

At this moment you should post the input xml and code you tried with.
__________________
Rummy
 
Old February 20th, 2009, 04:41 PM
Authorized User
 
Join Date: Feb 2009
Posts: 14
Thanks: 0
Thanked 0 Times in 0 Posts
Default Applying Templates Based on Attributes

I've included the code below. Any help is appreciated.

Thanks,
Josh


Here's the xml:

Code:
<book>
 <chapter layout="portrait">
   <title>Chapter 1 Title</title>
   <para>Content in the first chapter.</para>
 </chapter>
 <chapter layout="landscape">
   <title>Chapter 2 Title</title>
   <para>Content in the second chapter.</para>
 </chapter>
</book>
Here's the XSL (note, I've included both methods I was trying. The method using modes is commented out).
Code:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:output method="xml" indent="yes"/>
 
<!-- XSL-FO Master Pages -->
<xsl:template match="book">
<fo:root>
<fo:layout-master-set>
<fo:simple-page-master master-name="portrait" page-height="29.7cm" page-width="21.0cm" margin="2cm">
<fo:region-body/>
</fo:simple-page-master>
<fo:simple-page-master master-name="landscape" page-height="21.0cm" page-width="29.7cm" margin="2cm">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
 
<!-- XSL-FO Page Sequences -->
<fo:page-sequence master-reference="portrait">
<fo:flow flow-name="xsl-region-body">
<xsl:call-template name="chap-portrait"/>
<!--<xsl:apply-templates select="/book/chapter" mode="portrait"/>-->
</fo:flow>
 
</fo:page-sequence>
<fo:page-sequence master-reference="landscape">
<fo:flow flow-name="xsl-region-body">
<xsl:call-template name="chap-landscape"/>
<!--<xsl:apply-templates select="/book/chapter" mode="landscape"/>-->
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
 
<!-- Method using a named template. -->
<xsl:template match="chapter[@layout='portrait']" name="chap-portrait">
<fo:block>
<xsl:apply-templates/>
</fo:block>
</xsl:template>
 
<xsl:template match="chapter[@layout='landscape']" name="chap-landscape">
<fo:block>
<xsl:apply-templates/>
</fo:block>
</xsl:template>
 
<!-- Method using a mode. -->
<!--
<xsl:template match="chapter[@layout='portrait']" mode="portrait">
<fo:block>
<xsl:apply-templates/>
</fo:block>
</xsl:template>
 
<xsl:template match="chapter[@layout='landscape']" mode="landscape">
<fo:block>
<xsl:apply-templates/>
</fo:block>
</xsl:template>
-->
 
<xsl:template match="chapter/title">
<fo:block font-size="14pt" font-family="arial" space-after="14pt" font-weight="bold">
<xsl:apply-templates/>
</fo:block>
</xsl:template>
 
<xsl:template match="para">
<fo:block font-size="10pt" font-family="arial" space-after="10pt">
<xsl:apply-templates/>
</fo:block>
</xsl:template>
</xsl:stylesheet>
 
Old February 20th, 2009, 05:33 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

I can only comment on the code as written, not alternative variants that you might have tried before commenting them out. As written, you are calling both the named templates for each chapter using call-template, and therefore each chapter is output twice. When you use call-template to invoke a template by name, the match attribute on the template is ignored.

Go back to using apply-templates. Only call it once for each chapter. I would also add a fallback rule (even if only to catch errors) for chapters that aren't labelled either as portrait or landscape. You shouldn't need to use modes, that just complicates the issue.
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
 
Old February 21st, 2009, 07:31 PM
Authorized User
 
Join Date: Feb 2009
Posts: 14
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Okay, here's what I ended up with, which seems to work. So I guess the lesson learned is that I need to put the chapter[@layout='portrait'] or chapter[@layout='landscape'] bit on both the apply-templates select statement, AND the template's match statement.

Thanks Mr. Kay and everyone else for your help. I was afraid I was going to have to resort to some ugly modification of my xml to get this to work. This solution seems pretty slick.

Thanks again,
Josh


Code:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:output method="xml" indent="yes"/>
 
<!-- XSL-FO Master Pages -->
<xsl:template match="/">
<fo:root>
<fo:layout-master-set>
<fo:simple-page-master master-name="portrait" page-height="29.7cm" page-width="21.0cm" margin="2cm">
<fo:region-body/>
</fo:simple-page-master>
<fo:simple-page-master master-name="landscape" page-height="21.0cm" page-width="29.7cm" margin="2cm">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
 
<!-- XSL-FO Page Sequences -->
<fo:page-sequence master-reference="portrait">
<fo:flow flow-name="xsl-region-body">
<xsl:apply-templates select="/book/chapter[@layout='portrait']"/>
</fo:flow>
 
</fo:page-sequence>
<fo:page-sequence master-reference="landscape">
<fo:flow flow-name="xsl-region-body">
<xsl:apply-templates select="/book/chapter[@layout='landscape']"/>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
 
<!-- Templates -->
<xsl:template match="chapter[@layout='portrait']">
<fo:block>
<xsl:apply-templates/>
</fo:block>
</xsl:template>
 
<xsl:template match="chapter[@layout='landscape']">
<fo:block>
<xsl:apply-templates/>
</fo:block>
</xsl:template>
 
<xsl:template match="chapter/title">
<fo:block font-size="14pt" font-family="arial" space-after="14pt" font-weight="bold">
<xsl:apply-templates/>
</fo:block>
</xsl:template>
 
<xsl:template match="para">
<fo:block font-size="10pt" font-family="arial" space-after="10pt">
<xsl:apply-templates/>
</fo:block>
</xsl:template>
</xsl:stylesheet>





Similar Threads
Thread Thread Starter Forum Replies Last Post
Default Rows Based Upon Number of XML Attributes. Mr.T Infopath 0 November 5th, 2007 07:29 PM
need html attribute based on xml attributes charles95621 XSLT 1 May 24th, 2007 05:21 PM
Applying discount blkskullwork Javascript 1 January 11th, 2007 05:14 PM
Grouping based on attributes values Chamkaur XSLT 4 June 21st, 2006 05:51 AM
Applying a template with subreport nat246 Crystal Reports 0 December 12th, 2005 02:50 AM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.