Re: [xsl] How to output open/close tags independently?

Subject: Re: [xsl] How to output open/close tags independently?
From: Mike Ferrando <mikeferrando@xxxxxxxxx>
Date: Thu, 26 Dec 2002 05:34:20 -0800 (PST)
Edward,
I recently did this transforming a HTML table into XML nodes. I was
able to use the @colspan attribute in the TD to determine if the data
was to be nested under the previous heading. I had TD[1] which was
always the box number and TD[2] which was always the data. I had
count(TD)=2 in every TR.

I had the same problem you are talking about. I did two things.
1. I ran my nodes through a stylesheet that put a @PS attribute in
each TR. This effectively numbered all nodes.
  <variable name="PS">
    <xsl:number level="any"/>
  </xsl:variable>
2. I created a stylesheet that called these nodes by their value to
group them into sets TR[@PS&gt;50 and @PS&lt;75].
3. I wrote an empty node at the end of the table to close the last
node set.
4. Using the @colspan attribute (which is a number), I was able to
create a nested heirarchy of nodes by using '&amp;&lt;' and
'&amp;&gt; text around each nested element. Then I searched and
replaced when I was done. I then validated it. 

Finally, as I was thinking about this. I found that there are really
only three possibilities which are encountered when transforming my
HTML table.
1. colspan = next colspan
2. colspan < next colspan
3. colspan > next colspan

If the condition is 1 then you just close the node.
If the condition is 2 nothing is done (you are opening to deeper
nodes).
If the condition is 3, use the difference between the present node
and the next node as the constant. This constant is used in a
recursive template outputing the closing tag until the value of the
difference is null.

In all cases you begin the node set with the starting wrapper node
which is text <xsl:text>&amp;lt;C?&amp;gt;</xsl:text>. The closing
node will be determined by the nesting of the data. (? is the value
of the current colspan.)

Hope this helps,
Sincerely,
Mike Ferrando
Washington, DC

===HTML===
<TR PS="125">
  <TD valign="top" colspan="2"><B>BOX 8</B></TD>
  <TD valign="top" colspan="8">Biblical lore treated in great detail
in Jewish encyclopedia. Review of<I>Universal Jewish
Encyclopedia</I>, edited by Isaac Land.<I>Christian Science
Monitor</I>, 31 July [n.d.].</TD></TR>
<TR PS="126">
  <TD valign="top" colspan="2"/>
  <TD valign="top" colspan="8">[Billings, William]</TD></TR>
<TR PS="127">
  <TD valign="top" colspan="3"><B>BOX 8</B></TD>
  <TD valign="top" colspan="7">[Liner notes for]<I>American Psalms
and Fuguing Tunes</I>. Columbia Masterworks, Set M-434-
AM-434-MM-434.</TD></TR>
<TR PS="128">
  <TD valign="top" colspan="2"><B>BOX 8</B></TD>
  <TD valign="top" colspan="8">The birth of opera.<I>Medical Opinion
and Review</I>3, no. 11 (Nov. 1967).</TD></TR>

===XML===
&amp;lt;C1&amp;gt;<D1 PS="125" CT_B="8">Biblical lore treated in
great detail in Jewish encyclopedia. Review of<I>Universal Jewish
Encyclopedia</I>, edited by Isaac Land.<I>Christian Science
Monitor</I>, 31 July [n.d.].</D1>&amp;lt;/C1&amp;gt;
&amp;lt;C1&amp;gt;<D1 PS="126">[Billings, William]</D1>
  &amp;lt;C2&amp;gt;<D2 PS="127" CT_B="8">[Liner notes
for]<I>American Psalms and Fuguing Tunes</I>. Columbia Masterworks,
Set M-434- AM-434-MM-434.</D2>&amp;lt;/C2&amp;gt;&amp;lt;/C1&amp;gt;
&amp;lt;C1&amp;gt;<D1 PS="128" CT_B="8">The birth of opera.<I>Medical
Opinion and Review</I>3, no. 11 (Nov. 1967).</D1>&amp;lt;/C1&amp;gt;

===XSL===
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet   version="1.0"  
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
<xsl:output version="1.0" method="xml" indent="no" encoding="utf-8"
omit-xml-declaration="no" standalone="no" media-type="text/xml"/>

<xsl:param name="replace"/>
<xsl:template match="/">
    <xsl:text>&#xA;</xsl:text>
  <xsl:comment>
    <xsl:value-of select="concat(' Transformed with ', $replace,
'.xsl ')"/>
  </xsl:comment>
  <xsl:for-each select="comment()">
    <xsl:text>&#xA;</xsl:text>
    <xsl:comment>
      <xsl:value-of select="."/>
    </xsl:comment>
  </xsl:for-each>
    <xsl:text>&#xA;</xsl:text>
<XX>
  <xsl:apply-templates select="//TABLE"/>
<xsl:text>&#xA;</xsl:text>
</XX>
</xsl:template>

<!-- Series 1 PS=1-52 -->
<!-- 3-13; 15-22; 24-31; 33-48; 50-52 -->
<!-- Series 2 PS=53-828 -->
<!-- 55-774; 776; 778-828 -->
<!-- Series 3 PS=829-839 -->

<xsl:template match="TABLE">
  <xsl:apply-templates select="TR[@PS=1]"/>
  <xsl:apply-templates select="TR[@PS=53]"/>
  <xsl:apply-templates select="TR[@PS=829]"/>
</xsl:template>

<!-- series ** has no subseries -->
<xsl:template match="TR[@PS=829]">
    <xsl:variable name="el"
select="normalize-space(translate(TD[2]/H3/A[@name], ' ', '_'))"/>
    <xsl:text>&#xA;</xsl:text>
    <xsl:element name="{$el}">
      <xsl:attribute name="ID"><xsl:value-of select="concat('CL',
TD[2]/H3/A/@name)"/></xsl:attribute>
      <xsl:attribute name="CTS_B"><xsl:value-of
select="substring-after(TD[1], 'BOX ')"/></xsl:attribute>
        <xsl:apply-templates select="following-sibling::TR[@PS&gt;829
and @PS&lt;840]" mode="other"/>
      <xsl:text>&#xA;</xsl:text>
    </xsl:element>
</xsl:template>

<xsl:template match="TR[@PS&gt;829 and @PS&lt;840]" mode="other">
<xsl:variable name="num" select="number(TD[1]/@colspan) -1"/>
<xsl:variable name="fs_num"
select="number(following-sibling::TR/TD[1]/@colspan) -1"/>
  <xsl:text>&#xA;&#x9;&#x9;</xsl:text>
  <xsl:value-of select="concat('&lt;C', TD[1]/@colspan -1, '&gt;')"/>
    <xsl:element name="{concat('D', TD[1]/@colspan -1)}">
    <xsl:attribute name="PS"><xsl:value-of
select="@PS"/></xsl:attribute>
    <xsl:if test="TD[1]/A">
      <xsl:attribute name="XCT_ID"><xsl:value-of
select="TD[1]/A/@name"/></xsl:attribute>
    </xsl:if>
    <xsl:if test="TD[2][child::A]">
      <xsl:attribute name="C11"><xsl:value-of
select="concat(substring-before(TD[2]/A, ':'), ': ',
substring-after(TD[2]/A, ':'))"/></xsl:attribute>
      <xsl:attribute name="X_TARGET"><xsl:value-of
select="substring-after(TD[2]/A/@href, '#')"/></xsl:attribute>
    </xsl:if>
    <xsl:if test="string-length(TD[1])&gt;1">
      <xsl:attribute name="CT_B"><xsl:value-of
select="substring-after(TD[1], 'BOX ')"/></xsl:attribute>
    </xsl:if>
        <xsl:apply-templates select="TD[2]"/>
    </xsl:element>
<!-- greater than don't close -->
<!-- equal close -->
<!-- less than call count to close -->
  <xsl:if test="$fs_num &gt; $num">
  </xsl:if>
  <xsl:if test="$fs_num = $num">
    <xsl:value-of select="concat('&lt;/C', $num, '&gt;')"/>
  </xsl:if>
  <xsl:if test="$fs_num &lt; $num">
      <xsl:call-template name="count">
        <xsl:with-param name="num" select="$num"/>
        <xsl:with-param name="fs_num" select="$fs_num"/>
      </xsl:call-template>
  </xsl:if>
</xsl:template>

<xsl:template match="TD[2]">
  <xsl:apply-templates mode="td2"/>
</xsl:template>

<xsl:template match="A" mode="td2">
</xsl:template>

<xsl:template match="*" mode="td2">
  <xsl:element name="{name()}">
    <xsl:call-template name="attrib1"/>
      <xsl:apply-templates mode="td2"/>
  </xsl:element>
</xsl:template>

<xsl:template name="count">
<xsl:param name="num"/>
<xsl:param name="fs_num"/>
  <xsl:choose>
    <xsl:when test="$fs_num &lt; $num">
      <xsl:value-of select="concat('&lt;/C', $num, '&gt;')"/>
        <xsl:call-template name="count">
          <xsl:with-param name="num" select="$num -1"/>
          <xsl:with-param name="fs_num" select="$fs_num"/>
        </xsl:call-template>        
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="concat('&lt;/C', $num, '&gt;')"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<xsl:template name="attrib1">
  <xsl:for-each select="@*">
    <xsl:attribute name="{name()}">
      <xsl:value-of select="."/>
    </xsl:attribute>
  </xsl:for-each>
</xsl:template>

<xsl:template match="text()">
  <xsl:value-of select="translate(., '&#xA;', '')"/>
</xsl:template>

</xsl:stylesheet>



__________________________________________________
Do you Yahoo!?
Yahoo! Mail Plus - Powerful. Affordable. Sign up now.
http://mailplus.yahoo.com

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread