Re: [xsl] Transforming XML Blockquotes - Mixed Content

Subject: Re: [xsl] Transforming XML Blockquotes - Mixed Content
From: James Fuller <jim.fuller@xxxxxxxxxxxxxx>
Date: Thu, 14 Apr 2005 03:12:38 +0200
Wendell Piez wrote:

> Right. And (sadly) some of us old-timers sighed when we saw the post,
> because we knew (a) the problem wasn't easy, and (b) most attempts to
> handle it deal only with a subset of the actual problem (as you have
> noticed). This is usually okay in practice (often one only *has* a
> subset of the problem), but does require more fine-grained analysis of
> requirements, such as

Wendell is spot on....and this type of problem is probably the largest
use case that XSLT struggles with....

here is another possible approach to solving the problem using  a 2
stage transformation (i have used variables  so its easy to illustrate
the process)....


XML

<?xml version="1.0" encoding="ISO-8859-1" ?>
<root>
    Yadda Yadda Yadda <italic>Italic Yadda</italic> Yadda:
        <blockquote>Blah Blah Blah Blah</blockquote>
        Yackity <font>Yack</font> Yack and wh
</root>


XSLT

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>

  <xsl:variable name="list-of-elements" select="'italic font'"/>
 
  <xsl:template match="root">

    <!-- 1st step: admittedly weird kind of tokenization with <p> -->
    <xsl:variable name="result">
      <xsl:apply-templates/>
    </xsl:variable>
   
    <!-- 2nd step: create new tree -->
    <xsl:variable name="final">
     <xsl:apply-templates select="$result" mode="final"/>
    </xsl:variable>

    <!-- 3rd step: print out result -->
    <xsl:copy-of select="$final"/>

  </xsl:template>
 
 
  <xsl:template match="text()">
    <xsl:if test="normalize-space()">
      <p><xsl:value-of select="normalize-space(.)"/></p>
    </xsl:if>
  </xsl:template>
 
 
  <xsl:template match="*[contains($list-of-elements,name())]">
    <xsl:copy-of select="."/>
  </xsl:template>
 
 
  <xsl:template match="blockquote"><xsl:copy-of
select="."/></xsl:template>  
 
   
  <xsl:template match="*[contains($list-of-elements,name())]" mode="final">
    <p>
      <xsl:value-of select="preceding-sibling::node()[1]"/>
      <xsl:element name="{name()}">
        <xsl:value-of select="."/>
      </xsl:element>
      <xsl:value-of select="following-sibling::node()[1]"/>
    </p>
  </xsl:template>
 
 
  <xsl:template
match="p[preceding-sibling::node()[not(contains($list-of-elements,name()))]
and following-sibling::node()[not(contains($list-of-elements,name()))]]"
mode="final"/>

  <xsl:template match="p" mode="final">
   
    <xsl:choose>
    <xsl:when
test="preceding-sibling::node()[not(contains($list-of-elements,name()))]
and following-sibling::node()[not(contains($list-of-elements,name()))]">
   
    </xsl:when>
   
    <xsl:when
test="preceding-sibling::node()[1][contains($list-of-elements,name())]">
      <xsl:copy-of select="."/>
    </xsl:when>
    </xsl:choose>

  </xsl:template>
 
 
 
  <xsl:template match="blockquote"  mode="final"><xsl:copy-of
select="."/></xsl:template>
 
</xsl:stylesheet>

not tested, and pretty ugly

gl, Jim Fuller

Current Thread