Subject: RE: trouble with preceding:: and parsing xhtml
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Sat, 3 Oct 2009 21:17:13 +0100
|
You're nearly there: you want
preceding::div[@tid='field'][1]
Without the [1], you select all of them throughout the document; and if you
then use something like xsl:value-of (in XSLT 1.0) then you get the one that
is first in document order.
>Then I tried preceding::div[@tid='field' and last()]
last() always gives a number that is 1 or more. "and last()" converts this
number to a boolean, and any number other than 1 is treated as true. So
you're adding "and true()" to your predicate, which doesn't change its
result. You were probably thinking of
preceding::div[@tid='field'][last()]
which means
preceding::div[@tid='field'][position() = last()]
But numeric predicates attached to a reverse axis step count the nodes in
reverse document order: 1 is the nearest, and last() is the furthest. So the
correct predicate is [1].
Regards,
Michael Kay
http://www.saxonica.com/
http://twitter.com/michaelhkay
> -----Original Message-----
> From: Chris Wolf [mailto:cw10025@xxxxxxxxx]
> Sent: 03 October 2009 20:37
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: trouble with preceding:: and parsing xhtml
>
> I have some xhtml documents that I want to process with XSL.
> The patterns that I'm interested in have a series of
> occurances of "div" element in pairs as in:
>
> <xhtml...>
> <head/>
> <body..>
> <table...>
> <tr..>
> <td...>
> <div tid="field"><a href="...">Foo</a></div> <table...>
> <tr...> <td...> <div class="category_data">Bla,Bla,Bla</div>
> <...>
>
> this pattern of the two pairs of div variations repeats an
> arbitrary number of times throughout the document and there
> could be other "div" elements interspersed, but not with the
> same qualifying attributes.
>
>
> Note that the "div" with "class='category_data'" is not a
> descendant of the first "div[@tid='field']"
> I don't think these pairs of DIVs are siblings either (at the
> same level).
>
> Basically, I'm trying to generate XML of name-value pairs
> where the name
> comes from the content of the <a/> in the first
> "div[@tid='field']", and the value is the
> content of the second "div[@class='category_data']".
>
> So the output should be:
> <Field name="Foo">Bla,Bla,Bla</Field>
>
> Where the value of the "name" attribute is the content of the
> input doc's
> div[@tid='field']/a, i.e. in this example, 'Foo'
>
> ...and the content of "Field" is the content of the input doc's
> div[@class='category_data']
>
>
>
> Since the the second div is not a descendant of the first, I
> can't capture
> the <a/> content in a variable and call <xsl:apply-templates
> select="div[@class='category_data']"/>
> with a parameter.
>
> The question is how else to pass data from one template to
> another template?
>
> I tried "reaching back" from the second template by using
> preceding::div[@tid='field']
> but this retrieved the value of the first node matching
> "div[@tid='field']" not
> the immediately preceding node that matches, as I would have
> expected. Then I tried
> preceding::div[@tid='field' and last()] - same result; always
> the same value and
> always the value of the very first node that matched.
>
> I guess I have no idea how "preceding::" is supposed to work.
>
>
> I would greatly appreciate any help.
>
> Thanks,
>
> -Chris
>
> <xsl:stylesheet version="1.0"
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
> xmlns:h="http://www.w3.org/1999/xhtml">
>
> <xsl:output method="xml" indent="yes"/>
> <xsl:strip-space elements="div a"/>
>
> <xsl:template match="/">
> <xsl:message>***** ROOT</xsl:message>
> <xsl:apply-templates select="//h:div"/>
> </xsl:template>
>
> <xsl:template match="h:div[@tid='field']">
> <xsl:message>***** DIV1</xsl:message>
> <xsl:apply-templates select="h:div"/>
> </xsl:template>
>
> <xsl:template match="h:div[@class='category_data']">
> <xsl:param name="fname"/>
> <xsl:message>***** DIV2</xsl:message>
> <xsl:message>^<xsl:value-of
> select="preceding::h:div[@tid='field']"/>^</xsl:message>
> <xsl:element name="Field">
> <xsl:attribute name="name">
> <xsl:value-of select="preceding::h:div[@tid='field']"/>
> </xsl:attribute>
> <xsl:value-of select="."/>
> </xsl:element><xsl:text>
> </xsl:text>
> <xsl:apply-templates/>
> </xsl:template>
>
> <xsl:template match="text()">
> <xsl:message>***** TEXT</xsl:message>
> <xsl:apply-templates/>
> </xsl:template>
>
> </xsl:stylesheet>
|