xslt magic tricks with dita and framemaker

Post on 28-Jan-2018

76 Views

Category:

Software

2 Downloads

Preview:

Click to see full reader

TRANSCRIPT

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

top related