"The Ebook Developer's Toolbox" by Sanders Kleinfeld (O’Reilly Media) for ebookcraft 2016, presented by BookNet Canada and eBOUND Canada - March 31, 2016
12. Pop Quiz #1: XSLT is…
A: An acronym for “Extensible
Stylesheet Language Transformations”
B: A programming language
written in XML syntax
C: An official W3C Specification
D: All of the above
13. Pop Quiz #1: XSLT is…
A: An acronym for “Extensible
Stylesheet Language Transformations”
B: A programming language
written in XML syntax
C: An official W3C Specification
D: All of the above
(http://www.w3.org/TR/xs
14. XSLT is a tool for global,
programmatic markup
manipulation
15. <body>
<div class="section">
<p><b>Chapter 1</b></p>
HTML5 is really great,
because there are lots of new
elements to facilitate
meaningful
tagging of content.
<br/><br/>
Also, they deprecated a lot
of yucky <font
color="green">non-semantic
stuff.</font>
</div>
</body>
<body>
<section>
<h1>Chapter 1<h1>
<p>HTML5 is really great,
because there are lots of new
elements to facilitate
meaningful tagging of
content.</p>
<p>Also, they deprecated a
lot of yucky <span
style="color: green;">non-
semantic stuff.</span></p>
</section>
</body>
XSLT
? ?
18. But what about:
•Closing tags (</b>)
•Attributes (<b class="term">)
•Extra Whitespace (<b >)
your_markup.replace(/<(/)?b(s*[^>]*)>/g, '<$1em$2>')
19. A Stack Overflow Classic:
“You can’t parse [X]HTML with regex”
(http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags)
20. XSLT leverages a
functional* paradigm
* Many folks have salient objections to calling XSLT a functional programming
language (e.g., http://www.snoyman.com/blog/2012/04/xslt-rant.html), but
document processing with XSLT still embodies the spirit of functional programming,
and it feels pedantic to me to deny that.
25. Identity Stylesheet
in XSLT: Explained
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
BEGIN
stylesheet
END
stylesheet
BEGIN matching
function
Match any node (element,
attribute, text)
BEGIN copy matched node
(OPEN elem)
END Copy matched node
(CLOSE elem)
Select any
node
END matching
function
Run stylesheet against specified children of
26. Identity Stylesheet in XSLT: How it Works
<xsl:stylesheet
xmlns:xsl="http://www
.w3.org/1999/XSL/Tran
sform" version="1.0">
<xsl:template
match="@*|node()">
<xsl:copy>
<xsl:apply-
templates select="@*|
node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
<body>
<p class="greet">
Hello World
</p>
</body>
Stylesheet Input XHTML Output XHTML
27. Identity Stylesheet in XSLT: How it Works
<xsl:stylesheet
xmlns:xsl="http://www
.w3.org/1999/XSL/Tran
sform" version="1.0">
<xsl:template
match="@*|node()">
<xsl:copy>
<xsl:apply-
templates select="@*|
node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
<body>
<p class="greet">
Hello World
</p>
</body>
Stylesheet Input XHTML Output XHTML
28. Identity Stylesheet in XSLT: How it Works
<xsl:stylesheet
xmlns:xsl="http://www
.w3.org/1999/XSL/Tran
sform" version="1.0">
<xsl:template
match="@*|node()">
<xsl:copy>
<xsl:apply-
templates select="@*|
node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
<body>
<p class="greet">
Hello World
</p>
</body>
Stylesheet Input XHTML Output XHTML
<body>
</body>
29. Identity Stylesheet in XSLT: How it Works
<xsl:stylesheet
xmlns:xsl="http://www
.w3.org/1999/XSL/Tran
sform" version="1.0">
<xsl:template
match="@*|node()">
<xsl:copy>
<xsl:apply-
templates select="@*|
node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
<body>
<p class="greet">
Hello World
</p>
</body>
Stylesheet Input XHTML Output XHTML
<body>
</body>
30. Identity Stylesheet in XSLT: How it Works
<xsl:stylesheet
xmlns:xsl="http://www
.w3.org/1999/XSL/Tran
sform" version="1.0">
<xsl:template
match="@*|node()">
<xsl:copy>
<xsl:apply-
templates select="@*|
node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
<body>
<p class="greet">
Hello World
</p>
</body>
Stylesheet Input XHTML Output XHTML
<body>
</body>
31. Identity Stylesheet in XSLT: How it Works
<xsl:stylesheet
xmlns:xsl="http://www
.w3.org/1999/XSL/Tran
sform" version="1.0">
<xsl:template
match="@*|node()">
<xsl:copy>
<xsl:apply-
templates select="@*|
node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
<body>
<p class="greet">
Hello World
</p>
</body>
Stylesheet Input XHTML Output XHTML
<body>
<p>
</p>
</body>
32. Identity Stylesheet in XSLT: How it Works
<xsl:stylesheet
xmlns:xsl="http://www
.w3.org/1999/XSL/Tran
sform" version="1.0">
<xsl:template
match="@*|node()">
<xsl:copy>
<xsl:apply-
templates select="@*|
node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
<body>
<p class="greet">
Hello World
</p>
</body>
Stylesheet Input XHTML Output XHTML
<body>
<p>
</p>
</body>
33. Identity Stylesheet in XSLT: How it Works
<xsl:stylesheet
xmlns:xsl="http://www
.w3.org/1999/XSL/Tran
sform" version="1.0">
<xsl:template
match="@*|node()">
<xsl:copy>
<xsl:apply-
templates select="@*|
node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
<body>
<p class="greet">
Hello World
</p>
</body>
Stylesheet Input XHTML Output XHTML
<body>
<p>
</p>
</body>
34. Identity Stylesheet in XSLT: How it Works
<xsl:stylesheet
xmlns:xsl="http://www
.w3.org/1999/XSL/Tran
sform" version="1.0">
<xsl:template
match="@*|node()">
<xsl:copy>
<xsl:apply-
templates select="@*|
node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
<body>
<p class="greet">
Hello World
</p>
</body>
Stylesheet Input XHTML Output XHTML
<body>
<p class="greet">
</p>
</body>
35. Identity Stylesheet in XSLT: How it Works
<xsl:stylesheet
xmlns:xsl="http://www
.w3.org/1999/XSL/Tran
sform" version="1.0">
<xsl:template
match="@*|node()">
<xsl:copy>
<xsl:apply-
templates select="@*|
node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
<body>
<p class="greet">
Hello World
</p>
</body>
Stylesheet Input XHTML Output XHTML
<body>
<p class="greet">
</p>
</body>
36. Identity Stylesheet in XSLT: How it Works
<xsl:stylesheet
xmlns:xsl="http://www
.w3.org/1999/XSL/Tran
sform" version="1.0">
<xsl:template
match="@*|node()">
<xsl:copy>
<xsl:apply-
templates select="@*|
node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
<body>
<p class="greet">
Hello World
</p>
</body>
Stylesheet Input XHTML Output XHTML
<body>
<p class="greet">
</p>
</body>
37. Identity Stylesheet in XSLT: How it Works
<xsl:stylesheet
xmlns:xsl="http://www
.w3.org/1999/XSL/Tran
sform" version="1.0">
<xsl:template
match="@*|node()">
<xsl:copy>
<xsl:apply-
templates select="@*|
node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
<body>
<p class="greet">
Hello World
</p>
</body>
Stylesheet Input XHTML Output XHTML
<body>
<p class="greet">
Hello World
</p>
</body>
38. Identity Stylesheet in XSLT: How it Works
<xsl:stylesheet
xmlns:xsl="http://www
.w3.org/1999/XSL/Tran
sform" version="1.0">
<xsl:template
match="@*|node()">
<xsl:copy>
<xsl:apply-
templates select="@*|
node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
<body>
<p class="greet">
Hello World
</p>
</body>
Stylesheet Input XHTML Output XHTML
<body>
<p class="greet">
Hello World
</p>
</body>
40. You can override the identity templates with
other, more specific matching templates (just as
you override rules with other rules in CSS)
CSS XSLT
* {
font-size: 10px;
}
h1 {
/* Custom Handling */
font-size: 20px;
}
<xsl:template match="@*|
node()">
<xsl:copy>
<xsl:apply-templates
select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="h1">
<xsl:copy>
<!--Custom handling-->
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
41. Our first transform: Convert all
<p class="greet"> elements to <h1>s
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="p[@class='greet']">
<h1>
<xsl:apply-templates select="@*|node()"/>
</h1>
</xsl:template>
</xsl:stylesheet>
XPath matching all p elements with a clas
42. Our first transform: Convert all
<p class="greet"> elements to <h1>s
<xsl:stylesheet
xmlns:xsl="http://www.w3
.org/1999/XSL/Transform"
version="1.0">
<xsl:template
match="@*|node()">
<xsl:copy>
<xsl:apply-
templates select="@*|
node()"/>
</xsl:copy>
</xsl:template>
<xsl:template
match=“p[@class=‘greet’]
”>
<h1>
<xsl:apply-
templates select=“@*|
node()"/>
</h1>
</xsl:template>
</xsl:stylesheet>
<body>
<p class="greet">
Hello World
</p>
<p>What’s up?</p>
</body>
Stylesheet Input XHTML Output XHTML
43. Our first transform: Convert all
<p class="greet"> elements to <h1>s
<xsl:stylesheet
xmlns:xsl="http://www.w3
.org/1999/XSL/Transform"
version="1.0">
<xsl:template
match="@*|node()">
<xsl:copy>
<xsl:apply-
templates select="@*|
node()"/>
</xsl:copy>
</xsl:template>
<xsl:template
match=“p[@class=‘greet’]
”>
<h1>
<xsl:apply-
templates select=“@*|
node()"/>
</h1>
</xsl:template>
</xsl:stylesheet>
<body>
<p class="greet">
Hello World
</p>
<p>What’s up?</p>
</body>
Stylesheet Input XHTML Output XHTML
73. Pop Quiz #3: Write XSLT that drops
<strong> tags from the HTML below, but
preserves the text content inside the tags
INPUT XHTML
<p>Learning
<strong>XSLT</strong> is
awesome!</p>
DESIRED OUTPUT XHTML
<p>Learning XSLT is
awesome!</p>
74. Pop Quiz #3 Solution
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="strong">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
BEGIN match “strong”
element
Select child nodes (except
attributes) of matched
“strong” element
End match “strong”
element
79. “Rather than tailoring disconnected designs to
each of an ever-increasing number of web
devices, we can treat them as facets of the
same experience. We can design for an
optimal viewing experience, but embed
standards-based technologies into our designs
to make them not only more flexible, but more
adaptive to the media that renders them.”
— Ethan Marcotte
“Responsive Web Design”
http://alistapart.com/article/responsive-web-design
81. 1. Content is split into pages
(Safari for Mac) (iBooks for Mac)
82. 2. Content reflows from page to page
(iBooks for iPhone) (iBooks for iPad)
83. 3. Content settings are user-configurable
User #1’s settings User #2’s settings
84. 4. Single ebook archive for all platforms
(iBooks) (NOOK)
(Google Play)
(Kobo) (Kindle)*
(Universal
Ebook)
* Either converted to MOBI via KindleGen, or submitted to Amazon for conversio
86. Media Queries encapsulate CSS rules to
be applied only when certain display
conditions are satisfied, such as:
•Screen dimensions fall within a given
width/height range
•Screen is monochrome or color
•Screen orientation is portrait or
landscape
87. Media Query Syntax*
@media media-type and (media-feature)
{
/* CSS Rules to be applied */
}
al media type, followed by zero or more media featu
88. Some Key W3C-Specified
Media Types:
•all - applied on any device
•print - applied to output for printers
•speech - applied on screen readers
•screen - applied to any display that is
not print or speech, which encompasses
most Web browsers and readers
89. Kindle’s Custom Media Types*:
•amzn-kf8 - applied on any Kindle device
or app that supports Amazon’s
Kindle Format 8 specification
•amzn-mobi - applied to Kindle devices or
apps that support only the legacy MOBI 7
format.
* See Chapter 8 of Kindle Publisher Guidelines
90. Example #1:
Kindle’s Recommended Media
Queries for table handling*
@media amzn-mobi {
table.complex {
/* Suppress display of complex tables on MOBI and use fallback image instead */
display: none;
}
}
@media amzn-kf8 {
img.table_fallback {
/* Suppress display of table fallback images on KF8, which can support complex tables */
display: none;
}
}
* See Chapter 8 of Kindle Publisher Guidelines
91. Some Key W3C-Specified
Media Features:
•(min-|max-)width - query the width of the current display window.
•(min-|max-)device-width* - query the screen width of the device
•(min-|max-)height - query the height of the current display window
•(min-|max-)device-height* - query the screen height of the device
•orientation - query whether orientation is currently portrait or
landscape
•color - query whether the display is color
•monochrome - query whether the display is monochrome
* Deprecated in Media Queries Level 4
92. Example #2:
Media Query for iBooks for iPad
@media (min-device-width:768px)
and (max-device-width:1024px) {
#usernote::before {
content: “You are reading this on
iBooks for iPad";
}
}
94. Example #3:
Media query to target both
iBooks + KF8-enabled Kindle*
@media not amzn-mobi {
/* Styling for everything that _is not_
a MOBI 7 platform */
}
Queries for formatting Poetry on Kindle and EPUB”
96. Some Key W3C-Specified
Fragmentation Properties:*
•page-break-before - configure page
breaking rules before specified element(s)
•page-break-after - configure page
breaking rules after specified element(s)
•page-break-inside - configure page
breaking rules within specified element(s)
nger mandates “page-” prefix on these properties, but it’s a good id
97. page-break- properties accept the
following values
•auto - Defer to browser/ereader on
pagebreak here (default)
•avoid - Avoid pagebreak here
•always - Always pagebreak here
•left - Add one or two pagebreaks to
make next page a left page
•right - Add one or two pagebreaks to
make next page a right page
•inherit - Inherit pagebreak rules from
parent element*
* “page-break” rules are not inherited by default
100. Some More Key W3C-Specified
Fragmentation Properties:*
•orphans - specify minimum number of
lines within an element that must be
preserved before a page boundary (at
bottom of page)
•widows - specify minimum number of
lines within an element that must be
preserved after a page boundary (at top of
page)
* Default value is 2 for both properties
101. Example #3:
Require three paragraph lines to
“stay together” at both the
bottom and top of pages
p {
orphans: 3
widows: 3
}