xsl-list
[Top] [All Lists]

Re: [xsl] fo:external-graphic and xml:base

2009-11-23 05:54:35
On Sun, Nov 22 2009 03:24:40 +0000, ms419(_at_)freezone(_dot_)co(_dot_)uk wrote:
...
I think the problem is that the stylesheet uses the document() function
to get HTML pages from the web,

  <xsl:template match="html:a" mode="foo">
    <fo:block>
      <xsl:apply-templates select="document(@href)//html:body"/>
    </fo:block>
  </xsl:template>

- and these pages, e.g. http://ica-atom.org/docs/index.php?title=UM-2.1

- have some relative images,
e.g. /docs/images/thumb/b/bb/UM-2.1.png/500px-UM-2.1.png

The <img> elements are part of the HTML document, and so relative to
http://ica-atom.org/docs/index.php?title=UM-2.1, but I guess the
<external-graphic> elements aren't?

I tried adding an xml:base="" attribute,

  <xsl:template match="html:a" mode="foo">
    <fo:block xml:base="{(_at_)href}">
      <xsl:apply-templates select="document(@href)//html:body"/>
    </fo:block>
  </xsl:template>

FWIW, support for xml:base is in the XSL 2.0 Requirements
(http://www.w3.org/TR/xslfo20-req/#N67190).  Feedback on the
requirements and on the current Working Draft are always welcome.

...
How can I automatically convert these HTML pages to a PDF with XSL-FO?

As Florent noted, resolve-uri() is only in XPath 2.0.  You could do the
transformation to FO outside FOP using a XSLT 2.0 processor, or you
could merge the two URLs using XSLT 1.0.

I had the impression that this sort of problem had been covered before,
but I couldn't find a XSLT 1.0 solution in the list archives.  The
'merge-dirnames' template below is based on templates in the xmlroff
testing module (http://xmlroff.org/browser/trunk/testing/common.xsl),
though I had to add new code to handle your combination of 'http:' URL
plus absolute filename (and I haven't tested it, sorry).  There's also a
'dirname' template so you can get the dirname of first HTML page (not
that it's strictly necessary for the case that you've shown).

Regards,


Tony Graham                         
Tony(_dot_)Graham(_at_)MenteithConsulting(_dot_)com
Director                                  W3C XSL FO SG Invited Expert
Menteith Consulting Ltd                               XML Guild member
XML, XSL and XSLT consulting, programming and training
Registered Office: 13 Kelly's Bay Beach, Skerries, Co. Dublin, Ireland
Registered in Ireland - No. 428599   http://www.menteithconsulting.com
  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --
xmlroff XSL Formatter                               http://xmlroff.org
xslide Emacs mode                  http://www.menteith.com/wiki/xslide
Unicode: A Primer                               urn:isbn:0-7645-4625-2



  <xsl:variable name="DEBUG"/>

  <!-- merge-dirnames
     - $dirname1: Potential base for a relative directory name
     - $dirname2: directory name to merge
     - $separator: String to use when concatenating directories. Optional.
     -
     - Merge $dirname1 and $dirname2 such that if $dirname2 is
     - a relative path, the result is relative to $dirname1.
     -
     - Also handles if either name or both names are empty.
     -->
  <xsl:template name="merge-dirnames">
    <xsl:param name="dirname1"/>
    <xsl:param name="dirname2"/>
    <xsl:param name="separator" select="'/'"/>

    <xsl:if test="$DEBUG >= 2">
      <xsl:message>
        <xsl:text>merge-dirname:: dirname1: '</xsl:text>
        <xsl:value-of select="$dirname1"/>
        <xsl:text>'; dirname2: '</xsl:text>
        <xsl:value-of select="$dirname2"/>
        <xsl:text>'</xsl:text>
      </xsl:message>
    </xsl:if>

    <xsl:variable name="merged-dirname">
      <xsl:choose>
        <xsl:when test="substring($dirname2, 1, 5) = 'http:'">
          <xsl:value-of select="$dirname2"/>
        </xsl:when>
        <xsl:when test="$dirname1 != ''">
          <xsl:choose>
            <xsl:when test="$dirname2 != ''">
              <xsl:choose>
                <xsl:when test="substring($dirname2, 1, 1) = $separator">
                  <xsl:if test="substring($dirname1, 1, 7) = 'http://'">
                    <xsl:value-of select="concat('http://',
                      substring-before(substring($dirname1, 8), '/'))"/>
                  </xsl:if>
                  <xsl:value-of select="$dirname2"/>
                </xsl:when>
                <xsl:otherwise>
                  <xsl:value-of select="concat($dirname1, $separator, 
$dirname2)"/>
                </xsl:otherwise>
              </xsl:choose>
            </xsl:when>
            <xsl:otherwise>
              <xsl:value-of select="$dirname1"/>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:when>
        <xsl:otherwise>
          <xsl:choose>
            <xsl:when test="$dirname2">
              <xsl:value-of select="$dirname2"/>
            </xsl:when>
            <xsl:otherwise>
              <xsl:text>.</xsl:text>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <xsl:if test="$DEBUG >= 2">
      <xsl:message>
        <xsl:text>merge-dirname:: merged dirname: '</xsl:text>
        <xsl:value-of select="$merged-dirname"/>
        <xsl:text>'</xsl:text>
      </xsl:message>
      <xsl:message><xsl:text>&#10;</xsl:text></xsl:message>
    </xsl:if>

    <xsl:value-of select="$merged-dirname"/>
  </xsl:template>

  <!-- dirname
     - $string: Pathname for which to get the directory name
     - $separator: String separating directory names.  Default is '/'.
     -
     - Gets the directory name (the part before the last $separator)
     - of $string.
     -->
  <xsl:template name="dirname">
    <xsl:param name="string"/>
    <xsl:param name="separator" select="'/'"/>

    <xsl:variable name="the-rest" select="substring-after($string,
                                                          $separator)"/>

    <xsl:if test="$DEBUG >= 2">
      <xsl:message>
        <xsl:text>dirname:: $string: '</xsl:text>
        <xsl:value-of select="$string"/>
        <xsl:text>'; $the-rest: '</xsl:text>
        <xsl:value-of select="$the-rest"/>
        <xsl:text>'&#10;</xsl:text>
      </xsl:message>
    </xsl:if>
    <xsl:value-of select="substring-before($string, $separator)"/>

    <xsl:if test="contains($the-rest, '/')">
      <xsl:text>/</xsl:text>
      <xsl:call-template name="dirname">
        <xsl:with-param name="string" select="$the-rest"/>
      </xsl:call-template>
    </xsl:if>
  </xsl:template>

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--

<Prev in Thread] Current Thread [Next in Thread>