xsl-list
[Top] [All Lists]

Re: [xsl] ancestor/subsequent descendant test

2009-03-28 13:58:43

On 27 Mar 2009, at 09:51 , Trevor Nicholls wrote:

My input documents are allowed to contain nested sections. An optional
attribute marks out certain sections as significant. I want to detect a situation in which a section which contains a descendant significant section does not contain a subsequent INsignificant section (other than descendants of any significant sections). It's complicated because the nested sections
are not (necessarily) immediate descendants of each other.

I think this may be one of those situations which benefit
from looking at it in more than one way.  If I've understood
your requirement correctly, you want to detect a situation
that has two components (or more).  Actually, you name three
components: (1) a section, containing (2) a significant
section, and also (3) an insignificant section following the
significant one.

The complexity of formulating the test can vary a lot depending
on where you detect it from.  If all you want is to see an
error message during processing of the input, you can put the
test wherever it's most convenient.  And even if you don't
have that freedom but MUST detect it from a particular location,
it can be useful prep work to try three formulations:  can
you detect this situation from section (1)? from (2)? from (3)?

If I have understood you correctly, detecting the problem from
location (3) amounts to finding an insignificant section which
(a) has a preceding sibling which is a significant section, and
(b) is not, itself, a descendant of a significant section.
(Actually, I'm not sure whether being a descendant of a
significant section makes the situation OK or not -- if not,
adjust the test.)  You can match and handle such sections
with a template like this:

 <xsl:template match="section[not(@sig='Y')
   and preceding-sibling::section[(_at_)sig='Y']
   and not(ancestor::section[(_at_)sig='Y'])]">
<xsl:message>Section <xsl:value-of select="concat(@id,' (',normalize-space(.),')')"
     /> is a hanging section.</xsl:message>
  <xsl:apply-templates/>
 </xsl:template>

If the preceding significant section is not necessarily
a sibling, but might be a child of 'include', the expression
"preceding-sibling::section[(_at_)sig='Y']" will of course need
to become more complicated.

You can detect sections which appear in role (2) of this
configuration with a very similar pattern (use
following-sibling, not preceding-sibling).

And the property of sections in role (1) is that they
contain a descendant section in role (2) or role (3), so
a template for them could be

 <xsl:template match="section[
  descendant::section[ @sig='Y'
      and following-sibling::section[not(@sig='Y')]
    ]
  ]">
<xsl:message>Section <xsl:value-of select="concat(@id,' (',normalize-space(.),')')"
    /> contains a problem.</xsl:message>
  <xsl:apply-templates/>
 </xsl:template>

Add 'terminate="yes"' to any of these messages if you want this
to be a fatal error.

Your draft template makes things more complicated than they need
to be, by matching a significant section and then climbing to
its first ancestor section.  It would be simpler just to test for
following siblings which are insignificant sections, or (if
this is necessary) which are 'include' elements with insignificant
sections as children:

 <xsl:template match="section[(_at_)sig="Y"]>
  <xsl:if test="following-sibling::section[not(@sig='Y')]
   or following-sibling::include/section[not(@sig='Y')]
   ">
<xsl:message terminate="yes">Hanging section ... the horror! the horror!</xsl:message>
  </xsl:if>
  <!--* ... normal processing ... *-->
 </xsl:template>

I hope this helps.

--
****************************************************************
* C. M. Sperberg-McQueen, Black Mesa Technologies LLC
* http://www.blackmesatech.com
* http://cmsmcq.com/mib
* http://balisage.net
****************************************************************





--~------------------------------------------------------------------
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>
--~--