Cover image for XSLT Cookbook, 2nd Edition

Book description

Forget those funky robot toys that were all the rage in the '80s, XSLT (Extensible Stylesheet Transformations) is the ultimate transformer. This powerful language is expert at transforming XML documents into PDF files, HTML documents, JPEG files--virtually anything your heart desires. As useful as XSLT is, though, most people have a difficult time learning its many peculiarities. And now Version 2.0, while elegant and powerful, has only added to the confusion.

XSLT Cookbook, Second Edition wants to set the record straight. It helps you sharpen your programming skills and overall understanding of XSLT through a collection of detailed recipes. Each recipe breaks down a specific problem into manageable chunks, giving you an easy-to-grasp roadmap for integrating XSLT with your data and applications. No other XSLT book around employs this practical problem-solution-discussion format.

In addition to offering code recipes for solving everyday problems with XSLT 1.0, this new edition shows you how to leverage the improvements found in XSLT 2.0, such as how to simplify the string manipulation and date/time conversion processes. The book also covers XPath 2.0, a critical companion standard, as well as topics ranging from basic transformations to complex sorting and linking. It even explores extension functions on a variety of different XSLT processors and shows ways to combine multiple documents using XSLT. Code examples add a real-world dimension to each technique.

Whether you're just starting out in XSLT or looking for advanced techniques, you'll find the level of information you need in XSLT Cookbook, Second Edition.

Table of Contents

  1. XSLT Cookbook, 2nd Edition
  2. A Note Regarding Supplemental Files
  3. Preface
    1. Structure of This Book
    2. Conventions Used in This Book
    3. Using Code Examples
    4. Safari Enabled
    5. How to Contact Us
    6. Acknowledgments
      1. Second Edition Acknowledgments
      2. First Edition Acknowledgments
  4. 1. XPath
    1. Introduction
    2. 1.1. Effectively Using Axes
      1. Problem
      2. Solution
        1. Child and descendant axes
        2. Sibling axes
        3. Parent and ancestor axes
        4. Preceding and following axes
      3. Discussion
    3. 1.2. Filtering Nodes
      1. Problem
      2. Solution
      3. Discussion
    4. 1.3. Working with Sequences
      1. Problem
      2. Solution
        1. XPath 1.0
        2. XPath 2.0
      3. Discussion
    5. 1.4. Shrinking Conditional Code with If Expressions
      1. Problem
      2. Solution
        1. XPath 1.0
        2. XPath 2.0
      3. Discussion
    6. 1.5. Eliminating Recursion with for Expressions
      1. Problem
      2. Solution
        1. XPath 1.0
        2. XPath 2.0
        3. Aggregation
        4. Mapping
        5. Generating
        6. Expanding
        7. Joining
      3. Discussion
    7. 1.6. Taming Complex Logic Using Quantifiers
      1. Problem
      2. Solution
        1. XPath 1.0
        2. XPath 2.0
      3. Discussion
    8. 1.7. Using Set Operations
      1. Problem
      2. Solution
        1. XPath 1.0
        2. XPath 2.0
      3. Discussion
      4. See Also
    9. 1.8. Using Node Comparisons
      1. Problem
      2. Solution
        1. XPath 1.0
        2. XPath 2.0
      3. Discussion
    10. 1.9. Coping with XPath 2.0's Extended Type System
      1. Problem
      2. Solution
      3. Discussion
    11. 1.10. Exploiting XPath 2.0's Extended Type System
      1. Problem
      2. Solution
      3. Discussion
  5. 2. Strings
    1. Introduction
    2. 2.1. Testing If a String Ends with Another String
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. XSLT 2.0
      3. Discussion
    3. 2.2. Finding the Position of a Substring
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. XSLT 2.0
      3. Discussion
    4. 2.3. Removing Specific Characters from a String
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. XSLT 2.0
      3. Discussion
        1. XSLT 2.0
    5. 2.4. Finding Substrings from the End of a String
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. XSLT 2.0
      3. Discussion
    6. 2.5. Duplicating a String N Times
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. XSLT 2.0
      3. Discussion
        1. XSLT 1.0
      4. See Also
    7. 2.6. Reversing a String
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. XSLT 2.0
      3. Discussion
        1. XSLT 1.0
        2. XSLT 2.0
    8. 2.7. Replacing Text
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. XSLT 2.0
      3. Discussion
    9. 2.8. Converting Case
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. XSLT 2.0
      3. Discussion
        1. XSLT 2.0
      4. See Also
    10. 2.9. Tokenizing a String
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. XSLT 2.0
      3. Discussion
      4. See Also
    11. 2.10. Making Do Without Regular Expressions
      1. Problem
      2. Solution
      3. Discussion
    12. 2.11. Exploiting Regular Expressions
      1. Problem
      2. Solution
        1. Matching text patterns
        2. Tokenizing stylized text
        3. Replacing and augmenting text
        4. Parsing text to convert to XML
      3. Discussion
    13. 2.12. Using the EXSLT String Extensions
      1. Problem
      2. Solution
      3. Discussion
      4. See Also
  6. 3. Numbers and Math
    1. Introduction
    2. 3.1. Formatting Numbers
      1. Problem
      2. Solution
        1. Use xsl:decimal-format in conjunction with format-number()
        2. Use xsl:number
      3. Discussion
        1. Formatting numbers into columns using a fixed number of decimal places
        2. Formatting money like U.S. accountants
        3. Formatting numbers for many European countries
        4. Converting numbers to Roman numerals
        5. Creating column numbers like a spreadsheet
        6. Formatting numbers using Arabic characters
    3. 3.2. Rounding Numbers to a Specified Precision
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. XSLT 2.0
      3. Discussion
    4. 3.3. Converting from Roman Numerals to Numbers
      1. Problem
      2. Solution
      3. Discussion
    5. 3.4. Converting from One Base to Another
      1. Problem
      2. Solution
      3. Discussion
    6. 3.5. Implementing Common Math Functions
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. Absolute value: ckbk:abs(x)
        3. Square root: ckbk:sqrt(x)
        4. Logarithms: ckbk:log10(number), ckbk:log(number), and ckbk:logN(x,base)
        5. Power: ckbk:power(base,power)
        6. Factorial
        7. XSLT 2.0
      3. Discussion
    7. 3.6. Computing Sums and Products
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. XSLT 2.0
      3. Discussion
        1. XSLT 1.0
        2. XSLT 2.0
      4. See Also
    8. 3.7. Finding Minimums and Maximums
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. XSLT 2.0
      3. Discussion
    9. 3.8. Computing Statistical Functions
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. XSLT 2.0
      3. Discussion
        1. XSLT 1.0
        2. XSLT 2.0
    10. 3.9. Computing Combinatorial Functions
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. XSLT 2.0
      3. Discussion
    11. 3.10. Testing Bits
      1. Problem
      2. Solution
      3. Discussion
        1. XSLT 2.0
  7. 4. Dates and Times
    1. Introduction
      1. See Also
    2. 4.1. Calculating the Day of the Week
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. XSLT 2.0
      3. Discussion
    3. 4.2. Determining the Last Day of the Month
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. XSLT 2.0
      3. Discussion
      4. See Also
    4. 4.3. Getting Names for Days and Months
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. XSLT 2.0
      3. Discussion
        1. XSLT 1.0
        2. XSLT 2.0
      4. See Also
    5. 4.4. Calculating Julian and Absolute Day Numbers from a Specified Date
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. XSLT 2.0
      3. Discussion
    6. 4.5. Calculating the Week Number for aSpecified Date
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. XSLT 2.0
      3. Discussion
      4. See Also
    7. 4.6. Working with the Julian Calendar
      1. Problem
      2. Solution
      3. Discussion
    8. 4.7. Working with the ISO Calendar
      1. Problem
      2. Solution
      3. Discussion
      4. See Also
    9. 4.8. Working with the Islamic Calendar
      1. Problem
      2. Solution
      3. Discussion
      4. See Also
    10. 4.9. Working with the Hebrew Calendar
      1. Problem
      2. Solution
      3. Discussion
    11. 4.10. Formatting Dates and Times
      1. Problem
      2. Solution
        1. XSLT 2.0
      3. Discussion
        1. XSLT 1.0
        2. XSLT 2.0
        3. The date-format declaration
        4. The picture string
    12. 4.11. Determining Secular and Religious Holidays
      1. Problem
      2. Solution
      3. Discussion
  8. 5. Selecting and Traversing
    1. Introduction
    2. 5.1. Ignoring Duplicate Elements
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. XSLT 2.0
      3. Discussion
        1. XSLT 1.0
        2. XSLT 2.0
      4. See Also
    3. 5.2. Selecting All but a Specific Element
      1. Problem
      2. Solution
      3. Discussion
      4. See Also
    4. 5.3. Selecting Nodes by Context
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. XSLT 2.0
      3. Discussion
      4. See Also
    5. 5.4. Performing a Preorder Traversal
      1. Problem
      2. Solution
      3. Discussion
    6. 5.5. Performing a Postorder Traversal
      1. Problem
      2. Solution
      3. Discussion
    7. 5.6. Performing an In-Order Traversal
      1. Problem
      2. Solution
      3. Discussion
    8. 5.7. Performing a Level-Order Traversal
      1. Problem
      2. Solution
      3. Discussion
    9. 5.8. Processing Nodes by Position
      1. Problem
      2. Solution
      3. Discussion
        1. XSLT 2.0
      4. See Also
  9. 6. Exploiting XSLT 2.0
    1. Introduction
    2. 6.1. Convert Simple Named Templates to XSLT Functions
      1. Problem
      2. Solution
      3. Discussion
    3. 6.2. Prefer for-each-group over Muenchian Method of Grouping
      1. Problem
      2. Solution
        1. Group by values (group-by="expression")
        2. Group by adjacent nodes (group-adjacent="expression")
        3. Group by starting node (group-starting-with="pattern")
        4. Group by ending node (group-ending-with="pattern")
      3. Discussion
    4. 6.3. Modularizing and Modes
      1. Problem
      2. Solution
      3. Discussion
    5. 6.4. Using Types for Safety and Precision
      1. Problem
      2. Solution
        1. Use the as attribute on elements that hold or return data.
        2. Use the type attribute on elements that create data.
      3. Discussion
    6. 6.5. Avoiding 1.0 to 2.0 Porting Pitfalls
      1. Problem
      2. Solution
        1. Sequences do not transparently convert to atomic items
        2. Types do not transparently convert to other types
        3. Extra parameters are not ignored
        4. Stricter semantic checking will cause errors on questionable usage
      3. Discussion
    7. 6.6. Emulating Object-Oriented Reuse and Design Patterns
      1. Problem
      2. Solution
      3. Discussion
        1. Template method
        2. Chain of responsibility
        3. Decorator
    8. 6.7. Processing Unstructured Text with Regular Expressions
      1. Problem
      2. Solution
      3. Discussion
    9. 6.8. Solving Difficult Serialization Problems with Character Maps
      1. Problem
      2. Solution
      3. See Also
    10. 6.9. Outputting Multiple Documents
      1. Problem
      2. Solution
      3. Discussion
      4. See Also
    11. 6.10. Handling String Literals Containing Quote Characters
      1. Problem
      2. Solution
      3. Discussion
    12. 6.11. Understanding the New Capabilities of Old XSLT 1.0 Features
      1. Problem
      2. Solution
        1. xsl:apply-templates
        2. xsl:attribute
        3. xsl:call-template
        4. xsl:comment
        5. xsl:copy and xsl:copy-of
        6. xsl:element
        7. xsl:for-each
        8. xsl:key
        9. xsl:message
        10. xsl:number
        11. xsl:output
        12. xsl:param
        13. xsl:processing-instruction
        14. xsl:strip-space
        15. xsl:stylesheet
        16. xsl:template
        17. xsl:value-of
        18. xsl:variable
        19. xsl:with-param
        20. current()
        21. document()
        22. function-available()
        23. key()
        24. system-property()
      3. Discussion
  10. 7. XML to Text
    1. Introduction
    2. 7.1. Dealing with Whitespace
      1. Problem
      2. Solution
        1. Too much whitespace
        2. Too little whitespace
      3. Discussion
      4. See Also
    3. 7.2. Exporting XML to Delimited Data
      1. Problem
      2. Solution
        1. Create a CSV file from flat attribute-encoded elements
        2. Create a CSV file from flat element-encoded data
        3. Handle more complex mappings
        4. XSLT 2.0
      3. Discussion
    4. 7.3. Creating a Columnar Report
      1. Problem
      2. Solution
        1. XSLT 2.0
      3. Discussion
    5. 7.4. Displaying a Hierarchy
      1. Problem
      2. Solution
        1. XSLT 2.0
      3. Discussion
    6. 7.5. Numbering Textual Output
      1. Problem
      2. Solution
        1. Number siblings sequentially
        2. Start from a number other than one
        3. Number elements globally
        4. Number elements globally within a subcontext
        5. Number hierarchically
      3. Discussion
    7. 7.6. Wrapping Text to a Specified Width and Alignment
      1. Problem
      2. Solution
      3. Discussion
      4. See Also
  11. 8. XML to XML
    1. Introduction
    2. 8.1. Converting Attributes to Elements
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. XSLT 2.0
      3. Discussion
    3. 8.2. Converting Elements to Attributes
      1. Problem
      2. Solution
      3. Discussion
        1. XSLT 1.0
        2. XSLT 2.0
    4. 8.3. Renaming Elements or Attributes
      1. Problem
      2. Solution
      3. Discussion
    5. 8.4. Merging Documents with Identical Schema
      1. Problem
      2. Solution
      3. Discussion
    6. 8.5. Merging Documents with Unlike Schema
      1. Problem
      2. Solution
        1. Incorporate one document as a subpart of a parent document
        2. Weave two documents together
        3. Join elements from two documents to make new elements
      3. Discussion
      4. See Also
    7. 8.6. Splitting Documents
      1. Problem
      2. Solution
        1. XSLT 1.0
      3. Discussion
      4. See Also
    8. 8.7. Flattening an XML Hierarchy
      1. Problem
      2. Solution
      3. Discussion
    9. 8.8. Deepening an XML Hierarchy
      1. Problem
      2. Solution
        1. Add structure based on existing data
        2. Add structure to correct a poorly designed document
        3. XSLT 2.0
          1. Add structure based on existing data
          2. Add structure to correct a poorly designed document
      3. Discussion
        1. Add structure based on existing data
        2. Add structure to correct a poorly designed document
    10. 8.9. Reorganizing an XML Hierarchy
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. XSLT 2.0
      3. Discussion
        1. XSLT 1.0
        2. XSLT 2.0
      4. See Also
  12. 9. Querying XML
    1. Introduction
    2. 9.1. Performing Set Operations on Node Sets
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. XSLT 2.0
      3. Discussion
      4. See Also
    3. 9.2. Performing Set Operations on Node Sets Using Value Semantics
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. XSLT 2.0
      3. Discussion
    4. 9.3. Determining Set Equality by Value
      1. Problem
      2. Solution
      3. Discussion
    5. 9.4. Performing Structure-Preserving Queries
      1. Problem
      2. Solution
      3. Discussion
    6. 9.5. Joins
      1. Problem
      2. Solution
      3. Discussion
        1. XSLT 1.0
        2. XSLT 2.0
    7. 9.6. Implementing the W3C XML Query-UseCases in XSLT
      1. Problem
      2. Solution
      3. Discussion
        1. XSLT 1.0
        2. XSLT 2.0
      4. See Also
  13. 10. XML to HTML
    1. Introduction
    2. 10.1. Using XSLT as a Styling Language
      1. Problem
      2. Solution
      3. Discussion
      4. See Also
    3. 10.2. Creating Hyperlinked Documents
      1. Problem
      2. Solution
      3. Discussion
      4. See Also
    4. 10.3. Creating HTML Tables
      1. Problem
      2. Solution
      3. Discussion
        1. XSLT 1.0
        2. XSLT 2.0
    5. 10.4. Creating Frames
      1. Problem
      2. Solution
      3. Discussion
      4. See Also
    6. 10.5. Creating Data-Driven Stylesheets
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. XSLT 2.0
      3. Discussion
    7. 10.6. Creating a Self-Contained HTML Transformation
      1. Problem
      2. Solution
      3. Discussion
    8. 10.7. Populating a Form
      1. Problem
      2. Solution
      3. Discussion
      4. See Also
  14. 11. XML to SVG
    1. Introduction
    2. 11.1. Transforming an Existing Boilerplate SVG
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. XSLT 2.0
      3. Discussion
    3. 11.2. Creating Reusable SVG Generation Utilities for Graphs and Charts
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. Axis generation
        3. Bar generation
        4. XY plots
        5. Pie-slice generation
        6. Open-Hi-Lo-Close plots
        7. XSLT 2.0
      3. Discussion
    4. 11.3. Creating a Tree Diagram
      1. Problem
      2. Solution
      3. Discussion
      4. See Also
    5. 11.4. Creating Interactive SVG-Enabled Web Pages
      1. Problem
      2. Solution
      3. Discussion
      4. See Also
  15. 12. Code Generation
    1. Introduction
      1. XSLT 2.0
    2. 12.1. Generating Constant Definitions
      1. Problem
      2. Solution
      3. Discussion
    3. 12.2. Generating Switching Code
      1. Problem
      2. Solution
      3. Discussion
    4. 12.3. Generating Message-Handling Stub Code
      1. Problem
      2. Solution
      3. Discussion
    5. 12.4. Generating Data Wrappers
      1. Problem
      2. Solution
      3. Discussion
    6. 12.5. Generating Pretty Printers
      1. Problem
      2. Solution
      3. Discussion
    7. 12.6. Generating a Test Data-Entry Web Client
      1. Problem
      2. Solution
      3. Discussion
    8. 12.7. Generating Test-Entry Web CGI
      1. Problem
      2. Solution
      3. Discussion
    9. 12.8. Generating Code from UML Models via XMI
      1. Problem
      2. Solution
      3. Discussion
    10. 12.9. Generating XSLT from XSLT
      1. Problem
      2. Solution
      3. Discussion
      4. See Also
  16. 13. Vertical XSLT Application Recipes
    1. Introduction
    2. 13.1. Converting Visio VDX Documents to SVG
      1. Problem
      2. Solution
      3. Discussion
      4. See Also
    3. 13.2. Working with Excel XML Spreadsheets
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. XSLT 2.0
      3. Discussion
    4. 13.3. Generating XTM Topic Maps from UML Modelsvia XMI
      1. Problem
      2. Solution
      3. Discussion
      4. See Also
    5. 13.4. Generating Web Sites from XTM Topic Maps
      1. Problem
      2. Solution
        1. Sorting algorithms
        2. Programming languages
        3. Root topic
        4. Page elements and layout
      3. Discussion
      4. See Also
    6. 13.5. Serving SOAP Documentation from WSDL
      1. Problem
      2. Solution
      3. Discussion
      4. See Also
  17. 14. Extending and Embedding XSLT
    1. Introduction
    2. 14.1. Saxon Extension Functions
      1. XSLT 1.0 (Saxon Version 6.5.4)
        1. XSLT 2.0 (Saxon Version 8.x)
    3. 14.2. Saxon Extension Elements
      1. XSLT 1.0 (Saxon Version 6.5.4)
        1. XSLT 2.0 (Saxon Version 8.x)
    4. 14.3. Xalan-Java 2 Extension Functions
      1. XSLT 1.0 (Xalan-Java 2.6.2)
    5. 14.4. Java Extension Function Using the Class Format Namespace
    6. 14.5. Java Extension Function Using the Package Format Namespace
    7. 14.6. Java Extension Function Using the Java Format Namespace
    8. 14.7. Scripting Extension Function Using Inline Script Code
    9. 14.8. Xalan-Java 2 Extension Elements
    10. 14.9. Java Extension Element
    11. 14.10. Scripting Extension Elements
      1. XSLT 2.0
    12. 14.11. MSXML Extension Functions
      1. XSLT 1.0
        1. XSLT 2.0
      2. See Also
    13. 14.12. Using Saxon's and Xalan's Native Extensions
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. You want to output to more than one destination
        3. You want to split a complex transformation into a series of transformations in a pipeline
        4. You want to work with dates and times
        5. You need a more efficient implementation of set operations
        6. You want extended information about a node in the source tree
        7. You want to interact with a relational database
        8. You want to dynamically evaluate an XPath expression created at runtime
        9. You want to change the value of a variable
        10. You want to write first-class extension functions in XSLT 1.0
        11. XSLT 2.0
        12. You want to get an XPath expression to the current node
        13. You want to handle and recover from dynamic errors
      3. Discussion
      4. See Also
    14. 14.13. Extending XSLT with JavaScript
      1. Problem
      2. Solution
      3. Discussion
      4. See Also
    15. 14.14. Adding Extension Functions Using Java
      1. Problem
      2. Solution
      3. Discussion
      4. See Also
    16. 14.15. Adding Extension Elements Using Java
      1. Problem
      2. Solution
      3. Discussion
      4. See Also
    17. 14.16. Using XSLT from Perl
      1. Problem
      2. Solution
      3. Discussion
      4. See Also
    18. 14.17. Using XSLT from Java
      1. Problem
      2. Solution
      3. Discussion
      4. See Also
  18. 15. Testing and Debugging
    1. Introduction
    2. 15.1. Using xsl:message Effectively
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. XSLT 2.0
      3. Discussion
        1. XSLT 1.0
    3. 15.2. Tracing the Flow of Your Stylesheet Through Its Input Document
      1. Problem
      2. Solution
        1. XSLT 1.0
        2. XSLT 2.0
      3. Discussion
      4. See Also
    4. 15.3. Automating the Insertion of Debug Output
      1. Problem
      2. Solution
      3. Discussion
      4. See Also
    5. 15.4. Including Embedded Unit Test Data in Utility Stylesheets
      1. Problem
      2. Solution
      3. Discussion
    6. 15.5. Structuring Unit Tests
      1. Problem
      2. Solution
      3. Discussion
      4. See Also
    7. 15.6. Testing Boundary and Error Conditions
      1. Problem
      2. Solution
        1. Boundary-condition testing
        2. Error-condition testing
      3. Discussion
  19. 16. Generic and Functional Programming
    1. Introduction
      1. Extending the Content of Global Variables
      2. Using Template Tags
      3. See Also
        1. XSLT 1.0
        2. XSLT 2.0
    2. 16.1. Creating Polymorphic XSLT
      1. Problem
      2. Solution
      3. Discussion
      4. See Also
    3. 16.2. Creating Generic Element Aggregation Functions
      1. Problem
      2. Solution
      3. Discussion
      4. See Also
    4. 16.3. Creating Generic Bounded Aggregation Functions
      1. Problem
      2. Solution
      3. Discussion
    5. 16.4. Creating Generic Mapping Functions
      1. Problem
      2. Solution
      3. Discussion
    6. 16.5. Creating Generic Node-Set Generators
      1. Problem
      2. Solution
      3. Discussion
  20. Index
  21. About the Author
  22. Colophon
  23. Copyright