Altova Mailing List Archives>Archive Index >microsoft.public.xsl Archive Home >Recent entries >Thread Prev - Re: Last position [Thread Next] Re: Last positionTo: NULL Date: 4/1/2008 12:56:00 PM tshad wrote: >> <xsl:template match="REPORT"> >> <xsl:copy> >> <xsl:apply-templates select="FORMS/FORM/FIELDS/*"/> >> </xsl:copy> >> </xsl:template> >> >> <xsl:template match="FIELDS/*"> >> <form> >> <sectionNumber><xsl:value-of >> select="../../@SECCODE"/></sectionNumber> >> <primary>True</primary> >> <formName><xsl:value-of select="../../@FORMCODE"/></formName> >> <tagName><xsl:value-of select="name()"/></tagName> >> <value><xsl:value-of select="."/></value> >> </form> >> <xsl:if test="position() = last()"> >> <form> >> <sectionNumber><xsl:value-of >> select="../../@SECCODE"/></sectionNumber> >> <primary>True</primary> >> <formName><xsl:value-of select="../../@FORMCODE"/></formName> >> <tagName>FormFormats</tagName> >> <flags>0</flags> >> <format>0</format> >> <value> >> <xsl:apply-templates select="../../@*"/> >> </value> >> </form> >> </xsl:if> >> </xsl:template> >> >> <xsl:template match="FORM/@*"> >> <xsl:value-of select="concat(name(), '=', .)"/> >> <xsl:if test="position() != last()"> >> <xsl:text> </xsl:text> >> </xsl:if> >> </xsl:template> >> >> </xsl:stylesheet> >> > > Worked perfectly. > > I am confused as to why it did, however. > > In my file, I had: > > <xsl:apply-templates select="FORMS/FORM"/> > > which doesn't work - doesn't seem to handle the "xsl:if test" so I don't get > the extra form element. But it works perfectly for the other 3. It > displayes the 3 form elements just not the extra one inside the test. > > You changed it to: > > <xsl:apply-templates select="FORMS/FORM/FIELDS/*"/> > > and it handles it fine. I thought that "FORMS/FORM" would handle all the > child elements. Why do I need the /FIELDS/* ? If you do <xsl:apply-templates select="FORMS/FORM"/> then the XSLT processor looks for a matching template for 'FORM' elements and processes them with the matching template. The stylesheet does not have any template matching 'FORM' elements therefore a default template (built-in template <URL:http://www.w3.org/TR/xslt#built-in-rule>) is used which processes all child nodes of the 'FORM' element with a matching template. Part of the child nodes of the 'FORM' element are 'FIELDS' elements so these are processed, again with a default template as there is no template matching 'FIELDS' elements in the stylesheet. The default template processes all child _nodes_ while my suggestion (<xsl:apply-templates select="FORMS/FORM/FIELDS/*"/>) makes sure that only the child _elements_ are processed as that way you can use position() and last() to make sure you add an element after the last child element. > This last question is similar to the one I am going to ask with a more > expanded example: > > In this sample, we have 2 templates and 2 apply-templates. > > When we say: > > <xsl:apply-templates select="FORMS/FORM/FIELDS/*"/> > > How does it know to use the 1st template? The xsl:apply-templates above processes all child elements of 'FIELDS' elements. The only matching template for those elements is obviously <xsl:template match="FIELDS/*"> as that does exactly that, match child elements of 'FIELDS' elements. > And how does: > > <xsl:apply-templates select="../../@*"/> > > know to use the last template since there are no template names or ids? Pattern matching again, this processes all attribute nodes of the grandparent (which is a 'FORM' element in your XML sample). The only matching template is <xsl:template match="FORM/@*">. I think you need to study <URL:http://www.w3.org/TR/xslt#section-Applying-Template-Rules> and <URL:http://www.w3.org/TR/xslt#conflict>. -- Martin Honnen --- MVP XML http://JavaScript.FAQTs.com/ | ||||||
| Company | Legal | Press | Partners | Careers | Sitemap | Contact Us | Altova Blog | Mobile | Full Site | |||
|
