[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

Re: [xsl] From WordprocessingML inline styles to nested inline elements


Subject: Re: [xsl] From WordprocessingML inline styles to nested inline elements
From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
Date: Mon, 02 Apr 2007 15:57:33 -0400

Yves,

Okay, now I've thought about it for a few seconds (about all I have, sorry), and I agree: your second solution is nicer. It scales better.

Even if I do dislike name testing in XSLT. But your application is so meta that I think we can make an exception for you.

Cheers,
Wendell

At 08:52 AM 4/2/2007, you wrote:
Wendell,

thank you very much for your comments. (I have been on a leave so I couldn't reply earlier.)

I feel I should have been clearer about the "wicked" things I am trying to do. Please let me have another go. Basically, I am now tackling the task of transforming WordML inline styles in 3 steps:

1) Define the nesting hierarchy of the inline styles in a tiny XML file of its own. E.g.:

<style_nesting>
  <b><i><u/></i></b>
</style_nesting>

2) Apply a meta-stylesheet which will exploit the file from step 1 and generate an operating stylesheet that contains, among other things, template rules for translating the set of a run's "active" inline styles into elements that are properly nested around the run's text.

3) Transform WordML runs with inline styles using the operating stylesheet that resulted from step 2, going from

<w:r>
  <w:rPr>
    <w:i/>
    <w:b/>
  </w:rPr>
  <w:t>This is text in bold and italic.</w:t>
</w:r>

to

<b><i>This is text in bold and italic.</i></b>


All but my last posting as well as your suggestion and David's were based on the assumption that the configuration file is read at the operating stylesheet's run-time, i.e. in step 3. That stylesheet would accordingly only contain generic inline style processing code.


Having changed my mind, I would now like to evaluate the nesting hierarchy already at step 2 and generate a stylesheet with "hard-wired" style nesting for step 3.

Hence, I still have the nesting hierarchy available, but need to make different use of it, by *indirectly* deriving from it XSLT code that "materializes" the nesting of the styles. As I am again mainly interested in the "final", operating stylesheet's contents, I will not consider for the moment how to actually generate that code from the nesting hierarchy in the configuration file.

I can think of two approaches in the operating stylesheet:

a) Using an ordered set of modes (e.g. 1 - unnamed, 2 - style_i,
   3 - style_u etc.). This requires, however, a cascade of all
   the styles that could come next and may be active or not, established
   by the list of modes allowed next:

<xsl:template match="w:r[w:rPr/w:b]">
  <xsl:element name="b">
  <xsl:apply-templates select="." mode="style_i style_u style_x"/>
  </xsl:element>
</xsl:template>

<xsl:template match="w:r[w:rPr/w:i]" mode="style_i">
  <xsl:element name="i">
  <xsl:apply-templates select="." mode="style_u style_x"/>
  </xsl:element>
</xsl:template>

...


b) Using one rule and a recursive named template. This seems to be much more elegant, as the nesting hierarchy is stated just in one place, as a sequence of strings:


<xsl:template match="w:r">
  <xsl:call-template name="add_style">
    <xsl:with-param name="style_names_list"
      select="('b', 'i', 'u', 'NONE')"/>
  </xsl:call-template>
</xsl:template>

<xsl:template name="add_style">
  <xsl:param name="style_names_list"/>

  <xsl:variable name="current_style_name"
    select="$style_names_list[1]"/>

<xsl:choose>

    <xsl:when test="$current_style_name = 'NONE'">
      <xsl:value-of select="w:t"/>
    </xsl:when>

    <xsl:when test="w:rPr/*[local-name()=$current_style_name]">
      <xsl:element name="{$current_style_name}">
        <xsl:call-template name="add_style">
          <xsl:with-param name="style_names_list"
            select="remove($style_names_list, 1)"/>
        </xsl:call-template>
      </xsl:element>
    </xsl:when>

    <xsl:otherwise>
      <xsl:call-template name="add_style">
        <xsl:with-param name="style_names_list"
          select="remove($style_names_list, 1)"/>
      </xsl:call-template>
    </xsl:otherwise>

</xsl:choose>

</xsl:template>


The latter solution works almost fine. Just two questions remain:


1) Can you think of better approaches, or do you have suggestions on how to improve the above?

2) I tried, of course, to test for the empty sequence as recursion terminator instead of testing for the token 'NONE'. Unfortunately, neither of the following test expressions worked, with $style_names_list initially set to ('b', 'i', 'u'):

$style_names_list = ()
$current_style_name = ''
$current_style_name = ()

Which is the correct expression to test for the empty sequence that $style_names_list will evaluate to after its last item has been removed?

Yves


======================================================================
Wendell Piez                            mailto:wapiez@xxxxxxxxxxxxxxxx
Mulberry Technologies, Inc.                http://www.mulberrytech.com
17 West Jefferson Street                    Direct Phone: 301/315-9635
Suite 207                                          Phone: 301/315-9631
Rockville, MD  20850                                 Fax: 301/315-8285
----------------------------------------------------------------------
  Mulberry Technologies: A Consultancy Specializing in SGML and XML
======================================================================


Current Thread
Keywords