This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: processing nodes together with different attributes


Hi Sony,

> <par def='1'/>
> <par>
>   aa
> </par>
> <par def='2' list='bullet'/>
> <par def='2'><!--BULLET ENTRIES START-->
>   first bullet entry
> </par>
> <par>
>   second bullet entry
> </par>
> <par def='1'/><!--BULLET ENTRIES FINISH-->

Am I right that the par elements with def attributes set the type of
the par elements that follow them?  I'm a bit confused by the fact
that there are two par elements with a def attribute equal to 2.

There are a couple of approaches.

The first approach is to identify the type of each par element by
looking back and finding what the nearest 'def' attribute is set to -
if the nearest 'def' attribute is a '1' then it's a normal par element
- if it's a '2' then it's a list item. Here, you apply templates to
all the par elements at once:

  <xsl:apply-templates select="par" />

Now, to get the nearest 'def' attribute, you need to get the def
attribute of the nearest preceding sibling par element that has a def
attribute:

  preceding-sibling::par[@def][1]/@def

You can test this to work out what to do - basically whether to add a
'*' or not at the beginning of the par value:

<xsl:template match="par[string()]">
   <xsl:variable name="type"
                 select="preceding-sibling::par[@def][1]/@def" />
   <xsl:if test="$type = '2'">*</xsl:if>
   <xsl:value-of select="." />
   <xsl:text>&#xA;</xsl:text>
</xsl:template>

If you have different kinds of lists, then you can get at the list
type through the path:

  preceding-sibling::par[@list][1]/@list

This gets the nearest preceding par element that has a list attribute,
and then gets the value of that list attribute.

This is a nice, simple, approach but it might be a bit inefficient if
you have long sequences of par elements that have the same type.  For
each of them, it has to search all the way back for the nearest
preceding sibling with a def attribute in order to work out what to do
with its content.

If that's a problem, you could use the second approach, which is to
work through the par elements one by one, using modes to indicate the
type of output that should be generated. So apply templates to only
the first one, in 'normal' mode:

   <xsl:apply-templates select="par[1]" mode="normal" />

Then have templates that output the relevant information for the
particular par in normal mode and move onto the next par element:

<xsl:template match="par" mode="normal">
   <xsl:value-of select="." />
   <xsl:text>&#xA;</xsl:text>
   <xsl:apply-templates select="following-sibling::par[1]"
                        mode="normal" />
</xsl:template>

If the par element has a def attribute equal to '2', then change the
mode to a list:

<xsl:template match="par[@def = '2']" mode="normal">
   <xsl:if test="string()">
      <xsl:text />*<xsl:value-of select="." />
      <xsl:text>&#xA;</xsl:text>
   </xsl:if>
   <xsl:apply-templates select="following-sibling::par[1]"
                        mode="list" />
</xsl:template>

Then have a template that outputs the list items for the par elements,
when they're encountered in 'list' mode:

<xsl:template match="par" mode="list">
   <xsl:text />*<xsl:value-of select="." />
   <xsl:text>&#xA;</xsl:text>
   <xsl:apply-templates select="following-sibling::par[1]"
                        mode="list" />
</xsl:template>

Until, again, there's a par element with a def attribute equal to '1',
in which case you move back again into normal mode:

<xsl:template match="par[@def = '1']" mode="list">
   <xsl:if test="string()">
      <xsl:value-of select="." />
      <xsl:text>&#xA;</xsl:text>
   </xsl:if>
   <xsl:apply-templates select="following-sibling::par[1]"
                        mode="normal" />
</xsl:template>

With this approach, you should pass parameters from template to
template in list mode to work out what kind of list the par element
belongs to, for example:

<xsl:template match="par" mode="list">
   <xsl:param name="list-type" />
   <xsl:text />*<xsl:value-of select="." />
   <xsl:text>&#xA;</xsl:text>
   <xsl:apply-templates select="following-sibling::par[1]"
                        mode="list">
      <xsl:with-param name="list-type" select="$list-type" />
   </xsl:apply-templates>
</xsl:template>

I hope that helps,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/



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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]