 |
| 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
|
|
|
|

February 18th, 2009, 05:12 PM
|
|
Authorized User
|
|
Join Date: Feb 2009
Posts: 14
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
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>
|
|

February 19th, 2009, 02:45 AM
|
|
Friend of Wrox
|
|
Join Date: Jun 2008
Posts: 291
Thanks: 9
Thanked 29 Times in 29 Posts
|
|
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
|
|

February 19th, 2009, 01:51 PM
|
|
Authorized User
|
|
Join Date: Feb 2009
Posts: 14
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
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..
|
|

February 19th, 2009, 11:55 PM
|
|
Friend of Wrox
|
|
Join Date: Jun 2008
Posts: 291
Thanks: 9
Thanked 29 Times in 29 Posts
|
|
At this moment you should post the input xml and code you tried with.
__________________
Rummy
|
|

February 20th, 2009, 04:41 PM
|
|
Authorized User
|
|
Join Date: Feb 2009
Posts: 14
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
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>
|
|

February 20th, 2009, 05:33 PM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
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
|
|

February 21st, 2009, 07:31 PM
|
|
Authorized User
|
|
Join Date: Feb 2009
Posts: 14
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
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>
|
|
 |