Hi Robert,
The mode feature is not too mysterious. A mode provides an alternate way of
processing an element. You can define several templates that match on an element, but
with different mode attributes. Each such template does something different with the
element when you apply it with the mode name specified. When the stylesheet encounters
an xsl:apply-templates, it searches for the template that best matches the context,
and in the specified mode. If it helps, you can think of the main template without a
mode attribute as mode="" (as in <xsl:template match="section" mode=""> ) and
<xsl:apply-templates/> as <xsl:apply-templates mode=""/>. The "mode-without-name",
so to speak.
The first problem with your customization seems to be a typo: the mode name you
specified is "class.attributes", but it should be "class.attribute" (singular). Since
the stylesheet is using <xsl:apply-templates mode="class.attribute">, your template is
not applied because the mode name does not match.
Regarding your questions:
1. When creating a new attribute for output, do you need to create a
separate mode, or can you just use the class.attribute mode? Do you
also need to create a new mode for value -- I.e. width.value?
B: you don't need a mode for the width value, you can just generate another attribute
in the customized mode="class.attribute" template using xsl:attribute.
2. I'm unclear about which xsl statement is actually supposed to write
the width="" attribute into the output. xsl:apply-templates?
B: With a statement like this:
<xsl:attribute name="width">
<xsl:value-of select="@role"/>
</xsl:attribute>
The content of the <xsl:attribute> element becomes the value of the attribute. Your
current customization sets width to local-name(), which is the name of the element
being processed. That would result in a width="para" attribute in your output, which
would likely be ignored. You want to set it to the value of the role attribute.
3. I'm using roles for a lot of things here: in the mediaobject and
the imageobject. Is this a potential problem?
B: No, that's not a problem as long as the mode names are different.
Bob Stayton
Sagehill Enterprises
[email protected]
----- Original Message -----
From: "Robert Nagle" <[email protected]>
To: "Bob Stayton" <[email protected]>
Cc: "Nic Gibson" <[email protected]>; <[email protected]>
Sent: Wednesday, August 24, 2011 5:06 AM
Subject: Re: [docbook-apps] how to add a style attribute inside a P element? (Kindle
insanity!)
Hi, I need some more help about customizing html output so that I can
change the attribute name and value. I had posted the original
question -- see Bob's reply here.
http://lists.oasis-open.org/archives/docbook-apps/201108/msg00035.html
The case, if you remember was that I wanted to specify for
caption/para that the <p width="-30" or that the attribute would be
<p style="text-indent:0"
I understand the general logic of Bob's suggested solution but not the
specifics. In fact, my problem may be simply be that I do not
understand how modes work in XSL here. My questions are at the end:
In block.xsl I see for para:
**********************************
<xsl:template name="paragraph">
<xsl:param name="class" select="''"/>
<xsl:param name="content"/>
<xsl:variable name="p">
<p>
<xsl:choose>
<xsl:when test="$class != ''">
<xsl:call-template name="common.html.attributes">
<xsl:with-param name="class" select="$class"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="locale.html.attributes"/>
</xsl:otherwise>
</xsl:choose>
<xsl:copy-of select="$content"/>
</p>
</xsl:variable>
<xsl:choose>
<xsl:when test="$html.cleanup != 0">
<xsl:call-template name="unwrap.p">
<xsl:with-param name="p" select="$p"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="$p"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
********************
As Bob said (see bottom), <xsl:call-template
name="common.html.attributes"> will in turn apply templates in
mode="class.attribute"
In html.xsl
********************
<!-- Apply common attributes such as class, lang, dir -->
<xsl:template name="common.html.attributes">
<xsl:param name="inherit" select="0"/>
<xsl:param name="class" select="local-name(.)"/>
<xsl:apply-templates select="." mode="common.html.attributes">
<xsl:with-param name="class" select="$class"/>
<xsl:with-param name="inherit" select="$inherit"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="*" mode="common.html.attributes">
<xsl:param name="class" select="local-name(.)"/>
<xsl:param name="inherit" select="0"/>
<xsl:call-template name="generate.html.lang"/>
<xsl:call-template name="dir">
<xsl:with-param name="inherit" select="$inherit"/>
</xsl:call-template>
<xsl:apply-templates select="." mode="class.attribute">
*******************<<<<<<<**************calling class.attributes
<xsl:with-param name="class" select="$class"/>
</xsl:apply-templates>
<xsl:call-template name="generate.html.title"/>
</xsl:template>
In that same html.xsl, here is the mode class.attribute and
accompanying mode class.value
******************
<xsl:template match="*" mode="class.attribute">
<xsl:param name="class" select="local-name(.)"/>
<!-- permit customization of class attributes -->
<!-- Use element name by default -->
<xsl:attribute name="class">
<xsl:apply-templates select="." mode="class.value">
<xsl:with-param name="class" select="$class"/>
</xsl:apply-templates>
</xsl:attribute>
</xsl:template>
<xsl:template match="*" mode="class.value">
<xsl:param name="class" select="local-name(.)"/>
<!-- permit customization of class value only -->
<!-- Use element name by default -->
<xsl:value-of select="$class"/>
</xsl:template>
<xsl:template match="*" mode="width.value">
<xsl:param name="width" select="local-name(.)"/>
<!-- permit customization of class value only -->
<!-- Use element name by default -->
<xsl:value-of select="$width"/>
</xsl:template>
***********************************
I would expect that in my customization layer I could do this to get a
width=30px attribute. I have a
XML source:
<mediaobject role="wide-image-with-caption">
<imageobject role="html">
<imagedata role="html" fileref="web-images/wide1.jpg"/>
</imageobject>
<!-- contentwidth="500px"
contentdepth="334px-->
<caption>
<para role ="30px">This caption works perfectly in 600x800
but for 1024x768, the second line of the
caption looks nasty! For every hard problem there is a
solution which is simple,
obvious and wrong. </para>
</caption>
</mediaobject>
my stab at customization:
<xsl:template match="caption/para" mode="class.attributes">
<xsl:param name="class" select="local-name(.)"/>
<xsl:param name="width" select="local-name(.)"/>
*******************unsure about this, but following the pattern
<!-- permit customization of class attributes -->
<!-- Use element name by default -->
<xsl:attribute name="class">
<xsl:apply-templates select="." mode="class.value">
<xsl:with-param name="class" select="$class"/>
</xsl:apply-templates>
</xsl:attribute>
<xsl:attribute name="width">
<xsl:apply-templates select="." mode="class.value">
<xsl:with-param name="width" select="$width"/>
</xsl:apply-templates>
</xsl:attribute>
******************* I also tried hardcoding the value like I did here.
(Both xsl: attributes are
uncommmented here, but I tried using only one at a time)
<xsl:attribute name="width">20px</xsl:attribute>
<xsl:apply-templates></xsl:apply-templates>
</xsl:template>
That didn't produce anything different. I realize that hardcoding the
value of the attribute is not the typical case-- Bob mentioned doing
it as a value in the role attribute. But I wanted to try something
easy first. (and in fact, I changed the xpath in the match= to * just
to see what would happen-- same outcome).
1. When creating a new attribute for output, do you need to create a
separate mode, or can you just use the class.attribute mode? Do you
also need to create a new mode for value -- I.e. width.value?
2. I'm unclear about which xsl statement is actually supposed to write
the width="" attribute into the output. xsl:apply-templates?
3. I'm using roles for a lot of things here: in the mediaobject and
the imageobject. Is this a potential problem?
Any help on this matter is appreciated.
Robert
******************************************************
On Wed, Aug 3, 2011 at 12:01 PM, Bob Stayton <[email protected]> wrote:
Hi Robert,
The mechanism in the stylesheet that lets you customize class attributes can
also be used to add other attributes such as style or width. Most element
templates include something like this:
<xsl:apply-templates select="." mode="class.attribute">
If not, then it has this:
<xsl:call-template name="common.html.attributes">
which in turn applies templates in mode="class.attribute". The default
template in that mode is in html/html.xsl:
<xsl:template match="*" mode="class.attribute">
<xsl:param name="class" select="local-name(.)"/>
<!-- permit customization of class attributes -->
<!-- Use element name by default -->
<xsl:attribute name="class">
<xsl:apply-templates select="." mode="class.value">
<xsl:with-param name="class" select="$class"/>
</xsl:apply-templates>
</xsl:attribute>
</xsl:template>
As you can see, that template generates an attribute whose name is "class"
and whose value is determined using mode="class.value", which is the mode I
usually advise people to customize when they need to change the class value
for an element.
But you could expand this template to include additional <xsl:attribute>
elements to generate additional attributes, such as style or width. Since
this is a mode, you can write separate templates for each element that needs
to generate different extra attributes, using the match attribute on the
template to select a specific XPath pattern. How you determine the values
from your content is up to you. As Nic suggests, role attribute could be
used.
Bob Stayton
Sagehill Enterprises
[email protected]
----- Original Message ----- From: "Nic Gibson" <[email protected]>
To: "Robert Nagle" <[email protected]>
Cc: <[email protected]>
Sent: Wednesday, August 03, 2011 9:28 AM
Subject: Re: [docbook-apps] how to add a style attribute inside a P element?
(Kindle insanity!)
Hi Robert
I've been doing some of the same things you are doing here. I'm not
convinced that are right about the Kindle indenting (I'm looking at some
titles I worked on and we've used css classes for the indent and it's
working just fine).
For the width, I postprocess. I'm working on a set of scripts for a client
at the moment that takes an EPUB and does some mappings for the Kindle. I
may be able to make them available to you (the client is often happy for
code written for them to be put into the public domain).
There is no reason why you couldn't do both the things you are discussing
here using a customisation though. You could use a template that operates on
role attributes perhaps.
nic
On 3 Aug 2011, at 12:47, Robert Nagle wrote:
To add to my remarks:
one common Kindle formatting example is to output
to <p width=75"> or <p width=-20">
so it would be nice if we could have a general way to add an attribute
like "width" in some cases.
(I don't know if it would validate as XHTML though).
rj
On Wed, Aug 3, 2011 at 6:36 AM, Robert Nagle <[email protected]>
wrote:
I'm outputting a lot of epub and frequently I need to massage the
output so that the epub can be converted into the Kindle format.
One inherent problem with kindlegen is that it strips out most CSS
code and instead adds some formatting attributes inside individual
elements.
One example. You cannot turn off indenting in Kindle unless you
hardcode something like <p style="text-indent:0">
So I do post-processing, I would have to do a global search and replace:
Change <p class="no-indent"> to <p style="text-indent:0"> in all
instances.
Change <div class="caption"><p> to <div.caption><p
style="text-indent:0"> in all instances.
Change <p class="pullquote"> to <p style="text-indent:0"> in all
instances.
I wouldn't even know how to get started to do this in customization
layer.
I've seen this discussion
http://markmail.org/search/?q=class.attribute&q=list%3Aorg.oasis-open.lists.docbook-apps#query:class.attribute%20list%3Aorg.oasis-open.lists.docbook-apps%20from%3A%22Bob%20Stayton%22+page:1+mid:7jfjygrqiz5pc7bs+state:results
where css.decoration is mentioned as well as custom class values
http://www.sagehill.net/docbookxsl/HtmlCustomEx.html#CustomClassValues
I think the section on "custom class values" seems relevant, but I
can't follow the example.
YOu would need to add a custom attribute to these elements (style) as
well as values (text-indent:0).
Do you have an idea about how to attack this problem? Thanks.
--
Robert Nagle
6121 Winsome Ln #56C, Houston TX 77057-5581
(H) 713 893 3424/ (W) 832-251-7522 Carbon Neutral Since Jan 2010
http://www.robertnagle.info
--
Robert Nagle
6121 Winsome Ln #56C, Houston TX 77057-5581
(H) 713 893 3424/ (W) 832-251-7522 Carbon Neutral Since Jan 2010
http://www.robertnagle.info
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
Nic Gibson
Corbas Consulting
Digital Publishing Consultancy and Training
http://www.corbas.co.uk, +44 (0)7718 906817
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]