← all demos
xsl:stylesheet(
    exclude-result-prefixes="xlink suwl d",
    version="1.0",
    xmlns:d="http://docbook.org/ns/docbook",
    xmlns:suwl="http://nwalsh.com/xslt/ext/com.nwalsh.saxon.UnwrapLinks",
    xmlns:xlink="http://www.w3.org/1999/xlink",
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform")
  xsl:key(match="d:glossentry", name="glossentries", use="normalize-space(d:glossterm)")
  xsl:key(match="d:glossentry", name="glossentries", use="normalize-space(d:glossterm/@baseform)")
  template simple.xlink:
    param node := .
    param content :=
      apply
    param linkend := $node/@linkend
    param xhref := $node/@xlink:href
    if ($linkend or $xhref) and $node/ancestor::*[@xlink:href or @linkend]:
      xsl:message
        "WARNING: nested link may be undefined in output:"
        "<"
        <- name($node)
        choose:
          when $linkend:
            "@linkend = '"
            <- $linkend
            "'>"
          when $xhref:
            "@xlink:href = '"
            <- $xhref
            "'>"
        "nested inside parent element"
        <- name($node/parent::*)
    target.show :=
      choose:
        when $node/@xlink:show = 'new':
          "_blank"
        when $node/@xlink:show = 'replace':
          "_top"
        else:
    link :=
      choose:
        when $xhref and
                      (not($node/@xlink:type) or
                           $node/@xlink:type='simple'):
          is.idref :=
            choose:
              when starts-with($xhref,'#')
                            and (not(contains($xhref,'('))
                            or starts-with($xhref,
                                       '#xpointer(id(')):
                "1"
              else:
                "0"
          is.olink :=
            choose:
              when contains($xhref,'#') and
                 @xlink:role = $xolink.role:
                "1"
              else:
                "0"
          choose:
            when $is.olink = 1:
              call olink:
                content := $content
            when $is.idref = 1:
              idref :=
                call xpointer.idref:
                  xpointer := $xhref
              targets := key('id',$idref)
              target := $targets[1]
              call check.id.unique:
                linkend := $idref
              choose:
                when count($target) = 0:
                  xsl:message
                    "XLink to nonexistent id:"
                    <- $idref
                  copy $content
                else:
                  a
                    apply .
                    @href
                      call href.target:
                        object := $target
                    choose:
                      when $node/@xlink:title:
                        @title
                          <- $node/@xlink:title
                      else:
                        apply $target
                    if $target.show !='':
                      @target
                        <- $target.show
                    copy $content
            else:
              a
                apply .
                call id.attribute
                @href
                  <- $xhref
                if $node/@xlink:title:
                  @title
                    <- $node/@xlink:title
                choose:
                  when $target.show !='':
                    @target
                      <- $target.show
                  when $ulink.target !='':
                    @target
                      <- $ulink.target
                copy $content
        when $linkend:
          targets := key('id',$linkend)
          target := $targets[1]
          call check.id.unique:
            linkend := $linkend
          a
            apply .
            call id.attribute
            @href
              call href.target:
                object := $target
            apply $target
            copy $content
        else:
          copy $content
    choose:
      when function-available('suwl:unwrapLinks'):
        copy suwl:unwrapLinks($link)
      else:
        copy $link
  template inline.charseq:
    param content :=
      apply
    param contentwithlink :=
      call anchor
      call simple.xlink:
        content := $content
    param wrapper-name := span
    element {$wrapper-name}:
      call common.html.attributes
      call id.attribute
      call generate.html.title
      copy $contentwithlink
      call apply-annotations
  template inline.monoseq:
    param content :=
      apply
    param contentwithlink :=
      call anchor
      call simple.xlink:
        content := $content
    code
      apply .
      call id.attribute
      copy $contentwithlink
      call apply-annotations
  template inline.boldseq:
    param content :=
      apply
    param contentwithlink :=
      call anchor
      call simple.xlink:
        content := $content
    span
      apply .
      call id.attribute
      choose:
        when local-name(..) = 'title'
                      and (local-name(../..) = 'figure'
                      or local-name(../..) = 'example'
                      or local-name(../..) = 'table'):
          copy $contentwithlink
        else:
          strong
            copy $contentwithlink
      call apply-annotations
  template inline.italicseq:
    param content :=
      apply
    param contentwithlink :=
      call anchor
      call simple.xlink:
        content := $content
    em
      call common.html.attributes
      call id.attribute
      copy $contentwithlink
      call apply-annotations
  template inline.boldmonoseq:
    param content :=
      apply
    param contentwithlink :=
      call anchor
      call simple.xlink:
        content := $content
    choose:
      when local-name(..) = 'title'
                    and (local-name(../..) = 'figure'
                         or local-name(../..) = 'example'
                         or local-name(../..) = 'table'
                         or local-name(../..) = 'formalpara'):
        code
          call common.html.attributes
          call id.attribute
          copy $contentwithlink
          call apply-annotations
      else:
        strong
          call common.html.attributes
          call id.attribute
          code
            call generate.html.title
            call dir
            copy $contentwithlink
          call apply-annotations
  template inline.italicmonoseq:
    param content :=
      apply
    param contentwithlink :=
      call anchor
      call simple.xlink:
        content := $content
    em
      call common.html.attributes
      call id.attribute
      code
        call generate.html.title
        call dir
        copy $contentwithlink
        call apply-annotations
  template inline.superscriptseq:
    param content :=
      apply
    param contentwithlink :=
      call anchor
      call simple.xlink:
        content := $content
    sup
      call generate.html.title
      call id.attribute
      call dir
      copy $contentwithlink
      call apply-annotations
  template inline.subscriptseq:
    param content :=
      apply
    param contentwithlink :=
      call anchor
      call simple.xlink:
        content := $content
    sub
      call generate.html.title
      call id.attribute
      call dir
      copy $contentwithlink
      call apply-annotations
  match d:author:
    param content :=
      call person.name
    param contentwithlink :=
      call anchor
      call simple.xlink:
        content := $content
      call apply-annotations
    span
      call common.html.attributes
      call id.attribute
      copy $contentwithlink
  match d:editor:
    param content :=
      call person.name
    param contentwithlink :=
      call anchor
      call simple.xlink:
        content := $content
      call apply-annotations
    span
      call common.html.attributes
      call id.attribute
      copy $contentwithlink
  match d:othercredit:
    param content :=
      call person.name
    param contentwithlink :=
      call anchor
      call simple.xlink:
        content := $content
      call apply-annotations
    span
      call common.html.attributes
      call id.attribute
      copy $contentwithlink
  match d:authorinitials:
    call inline.charseq
  match d:accel:
    call inline.charseq
  match d:action:
    call inline.charseq
  match d:application:
    call inline.charseq
  match d:classname:
    call inline.monoseq
  match d:exceptionname:
    call inline.monoseq
  match d:interfacename:
    call inline.monoseq
  match d:methodname:
    call inline.monoseq
  match d:command:
    call inline.boldseq
  match d:computeroutput:
    call inline.monoseq
  match d:constant:
    call inline.monoseq
  match d:database:
    call inline.charseq
  match d:date:
    call inline.charseq
  match d:errorcode:
    call inline.charseq
  match d:errorname:
    call inline.charseq
  match d:errortype:
    call inline.charseq
  match d:errortext:
    call inline.charseq
  match d:envar:
    call inline.monoseq
  match d:filename:
    call inline.monoseq
  match d:function:
    choose:
      when $function.parens != '0'
                    and (d:parameter or d:function or d:replaceable):
        nodes := text()|*
        call inline.monoseq:
          content :=
            call simple.xlink:
              content :=
                apply $nodes[1]
        "("
        apply $nodes[position()>1]
        ")"
      else:
        call inline.monoseq
  match d:function/d:parameter (priority="2"):
    call inline.italicmonoseq
    if $function.parens != 0 and following-sibling::*:
      ","
  match d:function/d:replaceable (priority="2"):
    call inline.italicmonoseq
    if $function.parens != 0 and following-sibling::*:
      ","
  match d:guibutton:
    call inline.charseq
  match d:guiicon:
    call inline.charseq
  match d:guilabel:
    call inline.charseq
  match d:guimenu:
    call inline.charseq
  match d:guimenuitem:
    call inline.charseq
  match d:guisubmenu:
    call inline.charseq
  match d:hardware:
    call inline.charseq
  match d:interface:
    call inline.charseq
  match d:interfacedefinition:
    call inline.charseq
  match d:keycap:
    choose:
      when @function and normalize-space(.) = '':
        call inline.boldseq:
          content :=
            call gentext.template:
              context := 'keycap'
              name := @function
      else:
        call inline.boldseq
  match d:keycode:
    call inline.charseq
  match d:keysym:
    call inline.charseq
  match d:literal:
    call inline.monoseq
  match d:code:
    call inline.monoseq
  match d:medialabel:
    call inline.italicseq
  match d:shortcut:
    call inline.boldseq
  match d:mousebutton:
    call inline.charseq
  match d:option:
    call inline.monoseq
  match d:package:
    call inline.charseq
  match d:parameter:
    call inline.italicmonoseq
  match d:property:
    call inline.charseq
  match d:prompt:
    call inline.monoseq
  match d:replaceable (priority="1"):
    call inline.italicmonoseq
  match d:returnvalue:
    call inline.charseq
  match d:structfield:
    call inline.italicmonoseq
  match d:structname:
    call inline.charseq
  match d:symbol:
    call inline.charseq
  match d:systemitem:
    call inline.monoseq
  match d:token:
    call inline.charseq
  match d:type:
    call inline.charseq
  match d:userinput:
    call inline.boldmonoseq
  match d:abbrev:
    call inline.charseq:
      wrapper-name := abbr
  match d:acronym:
    call inline.charseq:
      wrapper-name := acronym
  match d:citerefentry:
    choose:
      when $citerefentry.link != '0':
        a
          apply .
          @href
            call generate.citerefentry.link
          call inline.charseq
      else:
        call inline.charseq
  template generate.citerefentry.link:
  template x.generate.citerefentry.link:
    "http://example.com/cgi-bin/man.cgi?"
    <- d:refentrytitle
    "("
    <- d:manvolnum
    ")"
  match d:citetitle:
    choose:
      when @pubwork = 'article':
        call gentext.startquote
        call inline.charseq
        call gentext.endquote
      else:
        call inline.italicseq
  match d:emphasis:
    span
      call id.attribute
      choose:
        when @role  and
                      normalize-space(@role) != '' and
                      $emphasis.propagates.style != 0:
          apply .
        else:
          apply .
      call anchor
      call simple.xlink:
        content :=
          choose:
            when @role = 'bold' or @role='strong':
              choose:
                when local-name(..) = 'title'
                              and (local-name(../..) = 'figure'
                              or local-name(../..) = 'example'
                              or local-name(../..) = 'table'):
                  apply
                else:
                  strong
                    apply
            when @role and $emphasis.propagates.style != 0:
              apply
            else:
              em
                apply
  match d:foreignphrase:
    span
      apply .
      call inline.italicseq
  match d:markup:
    call inline.charseq
  match d:phrase:
    span
      call id.attribute
      call locale.html.attributes
      choose:
        when @role and
                     normalize-space(@role) != '' and
                     $phrase.propagates.style != 0:
          apply .
        else:
          apply .
      call dir
      call anchor
      call simple.xlink:
        content :=
          apply
      call apply-annotations
  match d:quote:
    depth :=
      call dot.count:
        string :=
          xsl:number(level="multiple")
    span
      apply .
      choose:
        when $depth mod 2 = 0:
          call gentext.startquote
          call inline.charseq
          call gentext.endquote
        else:
          call gentext.nestedstartquote
          call inline.charseq
          call gentext.nestedendquote
  match d:varname:
    call inline.monoseq
  match d:wordasword:
    call inline.italicseq
  match d:lineannotation:
    em
      apply .
      call inline.charseq
  match d:superscript:
    call inline.superscriptseq
  match d:subscript:
    call inline.subscriptseq
  match d:trademark:
    call inline.charseq
    choose:
      when @class = 'copyright'
                    or @class = 'registered':
        call dingbat:
          dingbat := @class
      when @class = 'service':
        sup = SM
      else:
        call dingbat:
          dingbat := 'trademark'
  match d:firstterm:
    call glossterm:
      firstterm := 1
  match d:glossterm(firstterm := 0):
    content :=
      apply
    choose:
      when ($firstterm.only.link = 0 or $firstterm = 1) and @linkend:
        targets := key('id',@linkend)
        target := $targets[1]
        call check.id.unique:
          linkend := @linkend
        choose:
          when $target:
            a
              apply .
              @href
                call href.target:
                  object := $target
              call inline.italicseq:
                contentwithlink := $content
          else:
            call inline.italicseq:
              content := $content
      when not(@linkend)
                    and ($firstterm.only.link = 0 or $firstterm = 1)
                    and ($glossterm.auto.link != 0)
                    and $glossary.collection != '':
        term :=
          choose:
            when @baseform:
              <- @baseform
            else:
              <- .
        cterm := (document($glossary.collection,.)//d:glossentry[d:glossterm=$term])[1]
        glossary := //d:glossary[@role='auto']
        if count($glossary) != 1:
          xsl:message
            "Warning: glossary.collection specified, but there are"
            <- count($glossary)
            "automatic glossaries"
        glosschunk :=
          call href.target:
            object := $glossary
        chunkbase :=
          choose:
            when contains($glosschunk, '#'):
              <- substring-before($glosschunk, '#')
            else:
              <- $glosschunk
        choose:
          when not($cterm):
            xsl:message
              "There's no entry for"
              <- $term
              "in"
              <- $glossary.collection
            call inline.italicseq
          else:
            id :=
              call object.id:
                object := $cterm
            a(href="{$chunkbase}#{$id}")
              apply .
              call inline.italicseq:
                content := $content
      when not(@linkend)
                    and ($firstterm.only.link = 0 or $firstterm = 1)
                    and $glossterm.auto.link != 0:
        term :=
          choose:
            when @baseform:
              <- normalize-space(@baseform)
            else:
              <- normalize-space(.)
        targets := key('glossentries', $term)
        target := $targets[1]
        choose:
          when count($targets)=0:
            xsl:message
              "Error: no glossentry for glossterm:"
              <- .
              "."
            call inline.italicseq
          else:
            a
              apply .
              if @id or @xml:id:
                @name
                  <- (@id|@xml:id)[1]
              @href
                call href.target:
                  object := $target
              call inline.italicseq:
                content := $content
      else:
        call inline.italicseq
  match d:termdef:
    span
      apply .
      call gentext.template:
        context := 'termdef'
        name := 'prefix'
      apply
      call gentext.template:
        context := 'termdef'
        name := 'suffix'
  match d:sgmltag|d:tag:
    call format.sgmltag
  template format.sgmltag:
    param class :=
      choose:
        when @class:
          <- @class
        else:
          "element"
    content :=
      choose:
        when $class='attribute':
          apply
        when $class='attvalue':
          apply
        when $class='element':
          apply
        when $class='endtag':
          "</"
          apply
          ">"
        when $class='genentity':
          "&"
          apply
          ";"
        when $class='numcharref':
          "&#"
          apply
          ";"
        when $class='paramentity':
          "%"
          apply
          ";"
        when $class='pi':
          "<?"
          apply
          ">"
        when $class='xmlpi':
          "<?"
          apply
          "?>"
        when $class='starttag':
          "<"
          apply
          ">"
        when $class='emptytag':
          "<"
          apply
          "/>"
        when $class='sgmlcomment' or $class='comment':
          "<!--"
          apply
          "-->"
        else:
          apply
    code
      apply .
      call simple.xlink:
        content := $content
  match d:email:
    call inline.monoseq:
      content :=
        if not($email.delimiters.enabled = 0):
          "<"
        a
          apply .
          call id.attribute
          @href
            "mailto:"
            <- .
          apply
        if not($email.delimiters.enabled = 0):
          ">"
  match d:keycombo:
    action := @action
    joinchar :=
      choose:
        when $action='seq':
        when $action='simul':
          "+"
        when $action='press':
          "-"
        when $action='click':
          "-"
        when $action='double-click':
          "-"
        when $action='other':
        else:
          "+"
    foreach *:
      if position()>1:
        <- $joinchar
      apply .
  match d:uri:
    call inline.monoseq
  match d:menuchoice:
    shortcut := ./d:shortcut
    call process.menuchoice
    if $shortcut:
      "("
      apply $shortcut
      ")"
  template process.menuchoice:
    param nodelist := d:guibutton|d:guiicon|d:guilabel|d:guimenu|d:guimenuitem|d:guisubmenu|d:interface
    param count := 1
    choose:
      when $count>count($nodelist):
      when $count=1:
        apply $nodelist[$count=position()]
        call process.menuchoice:
          nodelist := $nodelist
          count := $count+1
      else:
        node := $nodelist[$count=position()]
        choose:
          when local-name($node)='guimenuitem'
                        or local-name($node)='guisubmenu':
            <- $menuchoice.menu.separator
          else:
            <- $menuchoice.separator
        apply $node
        call process.menuchoice:
          nodelist := $nodelist
          count := $count+1
  match d:optional:
    <- $arg.choice.opt.open.str
    call inline.charseq
    <- $arg.choice.opt.close.str
  match d:citation:
    targets := (//d:biblioentry | //d:bibliomixed)[d:abbrev = string(current())]
    target := $targets[1]
    choose:
      when $target and not(d:xref) and not(d:link):
        "["
        a
          apply .
          @href
            call href.target:
              object := $target
          choose:
            when $bibliography.numbered != 0:
              call id.attribute
              apply $target
            else:
              call inline.charseq
        "]"
      else:
        "["
        call inline.charseq
        "]"
  match d:citebiblioid:
    targets := //*[d:biblioid = string(current())]
    target := $targets[1]
    choose:
      when $target and not(d:xref) and not(d:link):
        "["
        a
          apply .
          @href
            call href.target:
              object := $target
          call inline.charseq
        "]"
      else:
        "["
        call inline.charseq
        "]"
  match d:biblioentry|d:bibliomixed (mode="citation"):
    xsl:number(count="d:biblioentry|d:bibliomixed", format="1", from="d:bibliography", level="any")
  match d:comment[&comment.block.parents;]|d:remark[&comment.block.parents;]:
    if $show.comments != 0:
      p(class="remark")
        em
          call inline.charseq
  match d:comment|d:remark:
    if $show.comments != 0:
      em
        call inline.charseq
  match d:productname:
    call inline.charseq
    if @class:
      call dingbat:
        dingbat := @class
  match d:productnumber:
    call inline.charseq
  match d:pob|d:street|d:city|d:state|d:postcode|d:country|d:otheraddr:
    call inline.charseq
  match d:phone|d:fax:
    call inline.charseq
  match d:honorific|d:firstname|d:givenname|d:surname|d:lineage|d:othername:
    call inline.charseq
  match d:person:
    param content :=
      apply d:personname
    param contentwithlink :=
      call anchor
      call simple.xlink:
        content := $content
      call apply-annotations
    span
      apply .
      call id.attribute
      copy $contentwithlink
  match d:personname:
    param content :=
      call person.name
    param contentwithlink :=
      call anchor
      call simple.xlink:
        content := $content
      call apply-annotations
    span
      apply .
      call id.attribute
      copy $contentwithlink
  match d:org:
    param content :=
      apply
    param contentwithlink :=
      call anchor
      call simple.xlink:
        content := $content
      call apply-annotations
    span
      apply .
      call id.attribute
      copy $contentwithlink
  match d:orgname:
    param content :=
      apply
    param contentwithlink :=
      call anchor
      call simple.xlink:
        content := $content
      call apply-annotations
    span
      apply .
      call id.attribute
      copy $contentwithlink
  match d:orgdiv:
    param content :=
      apply
    param contentwithlink :=
      call anchor
      call simple.xlink:
        content := $content
      call apply-annotations
    span
      apply .
      call id.attribute
      copy $contentwithlink
  match d:affiliation:
    param content :=
      call person.name
    param contentwithlink :=
      call anchor
      call simple.xlink:
        content := $content
      call apply-annotations
    span
      apply .
      call id.attribute
      copy $contentwithlink
  match d:beginpage:
  match &inline.elements; (mode="xref-to"):
    apply