Re: [xsl] Getting the first p inside a div

Subject: Re: [xsl] Getting the first p inside a div
From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
Date: Tue, 19 Aug 2008 12:02:11 -0400
Hi Walter,

Your solution isn't far off. You just need to alter the condition under which a p reaches and grabs the label to generate the anchor, so that it discriminates your cases properly. Right now, both the first p child of the note, and the first p inside any descendants of the note, pass the test in your match pattern "p[ancestor::note][1]". Consequently, you will get the label as many times as you have descendants containing p as well as for the first p child.

Something like this:

<xsl:template match="note//p">
<p class="note_p">
<xsl:if test="generate-id() = generate-id(ancestor::note/descendant::p[1])">
<xsl:apply-templates select="ancestor::note/label"/>
</xsl:if>
<xsl:apply-templates/>
</p>
</xsl:template>


What this does:

* Collapse the templates together for all p elements inside note, rather than splitting a template out for the first p. This is clearer, allows better code reuse, and is more robust.

* Fetches and processes the label only for the p that is first inside its ancestor note, at whatever level, thus getting around the problem when one appears inside a descendant (such as the cit). An XSLT 1.0 idiom for node identity testing is used for this. (In XSLT 2.0 this test could be written ". is ancestor::note/descendant::p[1]".)

A simpler solution would be to allow the anchor to appear just inside the div[@class='note'] in the output, and not even put it inside the p. Then the processing of the label could simply happen in the default traversal. This would also be stronger in the face of variant input (maybe you don't always get a p in the output, or you get a p for some other reason than matching a p in the input).

Cheers,
Wendell

At 11:20 AM 8/19/2008, you wrote:
I have some footnotes in text coded like this:

<note>
        <label/>
        <cit>
                <p/>
        </cit>
        <p/>
        <p/>
</note>

While others are coded like this:

<note>
        <label/>
        <p/>
        <p/>
</note>

I have a template which grabs the label and nests it inside the first
P in the note.

<xsl:template match="label[parent::note]">
<xsl:element name="a">
<xsl:for-each select="parent::note">
<xsl:attribute name="href">#c_<xsl:value-of select="@id"/></ xsl:attribute>
<xsl:attribute name="name"><xsl:value-of select="@id"/></ xsl:attribute>
<xsl:attribute name="id"><xsl:value-of select="@id"/></xsl:attribute>
</xsl:for-each>
<xsl:text>[</xsl:text>
<xsl:apply-templates/>
<xsl:text>]</xsl:text>
</xsl:element>
<xsl:text> </xsl:text>
</xsl:template>


<xsl:template match="p[ancestor::note][1]" priority="2">
        <xsl:element name="p">
                <xsl:attribute name="class">note_p</xsl:attribute>
                <xsl:apply-templates select="ancestor::note/label"/>
                <xsl:apply-templates/>
        </xsl:element>
</xsl:template>


This works just fine, until I encounter a note coded like this:


<note>
        <label/>
        <p/>
        <cit>
                <p/>
        </cit>
</note>

Then, I end up with two copies of the same anchor, like this:

<div class="footnote">
        <p>
                <a id="foo" ... >*</a>
                Footnote here.
        </p>
        <div class="cit">
                <p>
                        <a id="foo" ... >*</a>
                        Citation here.
                </p>
        </div>
</div>

I am stuck using XSL 1.0 for this -- is there a way I can choke off
my function after it fires the first time inside the note? Is there
another way I could be looking at this problem?

Thanks,

Walter


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