Upload
contrext-solutions
View
76
Download
2
Embed Size (px)
Citation preview
XSLT Magic Tricks with
DITA and FrameMaker
Eliot KimberContrext
Adobe DITA World 2017
About the Author
• Independent consultant focusing on DITA analysis, design, and implementation
• Doing SGML and XML for cough 30 years cough• Founding member of the DITA Technical
Committee• Founding member of the XML Working Group• Co-editor of HyTime standard (ISO/IEC 10744)• Primary developer and founder of the DITA for
Publishers project• Author of DITA for Practitioners, Vol 1 (XML
Press)
10/12/2017 Adobe DITA World 2
Agenda
• XSLT and FrameMaker
• XSLT Basics
• Configuring Your Structure Application
• Magic Tricks
• Resources
10/12/2017 Adobe DITA World 3
XSLT AND FRAMEMAKER
10/12/2017 Adobe DITA World 4
What is XSLT?
• “XML Style Sheet Language Transformations”
• Standard programming language for manipulating XML documents
10/12/2017 Adobe DITA World 5
Why is XSLT Interesting?
• Makes it easy to make small changes
• Makes it possible to do big changes
• Mature standard with lots of support in tools
• Same transform can be used in many environments
10/12/2017 Adobe DITA World 6
What Does XSLT Do?
• Takes as input one or more XML documents
• Produces as output any of:
– One or more XML documents
– Text data of any kind
– JSON (XSLT 3)
10/12/2017 Adobe DITA World 7
Transforms
• XSLT programs are “transforms”:– One or more XML documents in– One or more XML documents (or other
things) out
• Uses XML syntax:
<xsl:stylesheet><xsl:template …>…
</xsl:template></xsl:stylesheet>
10/12/2017 Adobe DITA World 8
XSLT in FrameMaker
• Configured as part of structure applications or associated with a specific document
• Can apply XSLT transforms on document open and document save
10/12/2017 Adobe DITA World 9
Which XSLT Engine?
• Can use Saxon or Xalan XSLT engine
• Use Saxon: Supports XSLT 2 and newer
• Saxon is the default
• Can use a newer version or licensed version of Saxon if desired
10/12/2017 Adobe DITA World 10
Why Use XSLT in FrameMaker
10/12/2017 Adobe DITA World 11
Alternative to Read/Write Rules
• XSLT applied before read rules and after write rules
• Can make it easier to adjust aspects of the XML on import and export
10/12/2017 Adobe DITA World 12
Generate Additional Outputs
• Use XSLT on export to generate additional outputs
– HTML files
– Reports
– Etc.
• Alternative to using DITA Open Toolkit or FrameMaker-provided features
10/12/2017 Adobe DITA World 13
Adjust XML
• Move elements around• Add elements or attributes needed by
FrameMaker• Group and sort elements (e.g., glossary
terms)• Add index entries based on markup• Adjust text details• Control line breaking in examples
– Add zero-width-spaces– Add non-breaking spaces
• Etc.
10/12/2017 Adobe DITA World 14
Validate Editorial and Business Rules
• Check things not checkable with DTDs or EDDs– Rules for content
– Co-occurrence rules (e.g., “if A is present then B must have attribute @foo”)
• Check rules not defined in the DTD or EDD that reflect local usage:– Require elements not required by DTD
– Require elements in a specific order
• Check rules for IDs, use of keys, etc.
10/12/2017 Adobe DITA World 15
Generalize on Import/Specialize on Export
• Enable use of specialized content with generic DITA FrameMakerapplication
• “Generalization”: Transforming specialized elements into one of their ancestors
• Generalization is always reversable
10/12/2017 Adobe DITA World 16
Generalization Example
• Source element: <mysection
class="- topic/section my-d/mysection ”
>
• Generalized:<section
class="- topic/section my-d/mysection ”
>
• @class attribute retains original specialization details
10/12/2017 Adobe DITA World 17
How Do I Do It?
10/12/2017 Adobe DITA World 18
Setting Up Structure Applications
• From Structured Application Designer go to “Advanced settings”
• Specify the XSLT transforms to use for preprocessing (before read rules) or postprocessing (after write rules)
• Or set up a transformations XML file and refer to that from the structure application
• See e.g., Structure\xml\DITA_1.3\app\technicalContent\xslt\DitaTransformations.xml
10/12/2017 Adobe DITA World 19
Pre- and Post-Processing Configuration
10/12/2017 Adobe DITA World 20
XSLT BASICS
10/12/2017 Adobe DITA World 21
Style Sheets
• Style sheet document root:
<xsl:stylesheet
xmlns:xsl=http://www.w3.org/1999/XSL/Transform
xmlns:xs=http://www.w3.org/2001/XMLSchema
exclude-result-prefixes="xs”
version="2.0">
… {templates go here}
</xsl:stylesheet>
10/12/2017 Adobe DITA World 22
Templates
• Templates apply rules to elements that match:<xsl:template match="body/p">
…
</xsl:template>
• Literal result elements:
<xsl:template match="body/p">
<new-p someatt="value">
<xsl:apply-templates/>
</new-p>
</xsl:template>
10/12/2017 Adobe DITA World 23
Nodes and Templates
• XSLT treats XML documents as trees of nodes:– Elements– Attributes– Text nodes
• Input document is processed as a tree starting with the document root node
• Templates are “applied” to nodes• The first template that matches a node
handles it
10/12/2017 Adobe DITA World 24
Match Templates and Context
• Templates use XPath expressions to match elements (and other types of nodes):<xsl:template match="body/p">
• XPath expression “body/p” matches any <p> element that is a child of a <body> element
10/12/2017 Adobe DITA World 25
Default Template
• Default template: matches any node and applies templates to its child nodes
10/12/2017 Adobe DITA World 26
Context Node
• The node that matches a template is that template’s context node
• “.” in XPath expressions refers to the context node:
<xsl:sequence select="."/>
10/12/2017 Adobe DITA World 27
Applying Templates to Nodes
• Within a template, process additional nodes by applying templates to those nodes:
<xsl:template match="body/p">
<mypara>
<xsl:apply-templates/>
</mypara>
</xsl:template>
• The xsl:apply-templates instruction applies templates to all child nodes of the current node by default
• Can select specific nodes if you want
10/12/2017 Adobe DITA World 28
Selecting Specific Nodes
• Can select specific nodes with xsl:apply-templates:
<xsl:template match="fig"><fig><xsl:apply-templates
select="(image|table|figgroup), title”/>
</fig></xsl:template>
• Here the @select attribute says “process all <image>, <table>, or <figgroup> elements then process any <title> elements.”
• This example puts the <title> after the main contents of the figure
10/12/2017 Adobe DITA World 29
Identity Transformations
• Identity transformations take a document as input and produce the equivalent document as output
• Form the base for most of what you’ll want to do with FrameMaker
10/12/2017 Adobe DITA World 30
Typical Identity Transform
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="*" priority="-1">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
<xsl:template
match="text()| @* | comment() |
processing-instruction()">
<xsl:sequence select="."/>
</xsl:template>
10/12/2017 Adobe DITA World 31
1
2
3
Identity Transform Part 1
• Matches the document root (“/”) and applies templates to all the child nodes of the root:
10/12/2017 Adobe DITA World 32
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
Identity Transform Part 2
• Matches any element node (“*”) • The @priority attribute value of “-1” means
“make this template a lower priority than any template with a default priority.– Makes it easy to add templates for specific
elements without worrying about priority
10/12/2017 Adobe DITA World 33
<xsl:template match="*" priority="-1">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
Identity Transform Part 2
• Creates a copy of the element:
<xsl:copy>…
</xsl:copy>
• Applies templates to all the attributes:
<xsl:apply-templates select="@*"/>
• Applies templates to all the child nodes:
<xsl:apply-templates select="node()"/>
10/12/2017 Adobe DITA World 34
Identity Transform Part 3
• Handles nodes that can’t have children:– Text nodes, attributes, comments, and
processing instructions
• Simply copies the input node to the output:
<xsl:sequence select="."/>
10/12/2017 Adobe DITA World 35
<xsl:template
match="text()| @* | comment() |
processing-instruction()">
<xsl:sequence select="."/>
</xsl:template>
Identity Transform Part 3
• The xsl:sequence instruction simply outputs the value of the @selectattribute
• Here “.” means “the current context node”, which is whatever node matched this template
10/12/2017 Adobe DITA World 36
<xsl:template
match="text()| @* | comment() |
processing-instruction()">
<xsl:sequence select="."/>
</xsl:template>
XSLT Modules
• Can organize style sheets into two or more files• One file is always the top-level module• Can “import” or “include” modules• For simple transforms always use “import”
– Avoids complexities around template priority– Last module imported has highest priority among
the imported modules– Importing (top-level) module always has highest
priority
• Don’t put “catch all” templates in top-level module– Cannot be overridden by imported modules
10/12/2017 Adobe DITA World 37
Two-Module Identity Transform
• Base module has base identity transform• Top-level module has overrides• Base module: identity.xsl
– Provides the generic identity transform templates
• Top-level module: imports identity.xsl:<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:import href="identity.xsl"/>
<xsl:template match="fig">...
</xsl:template></xsl:stylesheet>
• Call the top-level module from your structured application
10/12/2017 Adobe DITA World 38
MAGIC TRICKS
10/12/2017 Adobe DITA World 39
Trick: Make Notes Into Hazard Statements
• Find <note> elements with @type of
“caution”, “warning”, or “danger”
• Change them into <hazardstatement> elements on
document open
10/12/2017 Adobe DITA World 40
Step 1: Implement Transform
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0"><!-- Convert notes of type "warning", "caution", and "danger"
to hazard statements.-->
<xsl:import href="../common/identity.xsl"/>
<xsl:output indent="yes"/>
<xsl:templatematch="*[contains(@class, ' topic/note ')]
[@type = ('warning', 'caution', 'danger')]"><hazardstatement><xsl:sequence select="@*"/><messagepanel><typeofhazard>[type of hazard]</typeofhazard><consequence><xsl:apply-templates/></consequence><howtoavoid>{how to avoid}</howtoavoid>
</messagepanel></hazardstatement>
</xsl:template></xsl:stylesheet>
10/12/2017 Adobe DITA World 41
Step 2: Add to Structure Application
10/12/2017 Adobe DITA World 42
Step 3: Try It
10/12/2017 Adobe DITA World 43
Before:
After:
Trick: Move Figure Titles To Bottom of Figure
• DITA content models put figure titles at top of figure
• Typical print layout puts them at bottom of figure
• Nice to have this in the editor
10/12/2017 Adobe DITA World 44
Step 1: Hack the DTDs
• Requires hacking DITA <fig> content model to allow <title> at end of figure
• E.g., modify commonElements.mod in the FrameMakercopy of the DITA DTDs:
<!-- LONG NAME: Figure --><!ENTITY % fig.content
"((%title;)?, (%desc;)?, (%figgroup; | %fig.cnt;)*,((%title;)?,(%desc)?)?)"
>
• No need to change the EDD unless you want structure view to not flag figure content as invalid.
10/12/2017 Adobe DITA World 45
Step 2: Pair of Transforms
• Transform one: moves <title> and <desc> to end of figures on open
– Preprocessing transform
• Transform two: moves <title> and <desc> back to top of figures on save
– Postprocessing transform
• Both are based on identity transform
10/12/2017 Adobe DITA World 46
One Challenge: DOCTYPE
• Transform needs to set the DOCTYPE declaration correctly, especially on save
• XSLT doesn’t allow dynamically setting of main result file DOCTYPE values
• Two solutions:
– One top-level transform per topic type
– Use disable-output-escaping to construct DOCTYPE declaration dynamically
• See built-in AdjustTableWidth.xsl for example
10/12/2017 Adobe DITA World 47
Step 3: Update Structure App
• For each topic type add Preprocessing and Postprocessingentries to XSLT Preferences settings
10/12/2017 Adobe DITA World 48
XSLT Preferences Sample
10/12/2017 Adobe DITA World 49
Step 4: Try It
10/12/2017 Adobe DITA World 50
Before: After:
Postprocessing Undoes Preprocessing
• The moved title is only seen in the Author view in FrameMaker
• The postprocessing transform is applied on save
• Also applied when switching to XML view
• No chance of getting invalid DITA content outside of FrameMaker
10/12/2017 Adobe DITA World 51
RESOURCES
10/12/2017 Adobe DITA World 52
Online XSLT Resources
• XSLT 2 specification: http://www.w3.org/TR/xslt20/
• XPath specification: http://www.w3.org/TR/xpath20/
• XQuery and Xpath 2 functions and operators: http://www.w3.org/TR/xpath-functions/
• Ken Holman’s XSLT book: http://www.cranesoftwrights.com/training/index.htm#ptux
• XSL mailing list (searchable with MarkMail): http://mulberrytech.com/xsl/xsl-list/index.html
10/12/2017 Adobe DITA World 53
Books
• Mike Kay’s XSLT 2.0 and XPath 2.0 Programmer’s Reference: http://www.wrox.com/WileyCDA/WroxTitle/XSLT-2-0-and-XPath-2-0-Programmer-s-Reference-4th-Edition.productCd-0470192747.html– Authoritative reference to the standard.
Not a beginner’s guide
• Search Amazon for “XSLT”. Look for books that reflect XSLT 2 or later
10/12/2017 Adobe DITA World 54
Questions?
10/12/2017 Adobe DITA World 55