Subject: Finding the first child element
Posted By: humansky Post Date: 4/17/2008 7:59:38 AM
Ok, so I've been having loads of problems trying to find the first child element in a given XML tree. Here is the example XML:

<page-components>
  <courses-component />
  <courses-component />
  <courses-component />
  <courses-component />
</page-components>

And here is the associated XSLT (that does not work):

<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>

<xsl:template match="/">
  <xsl:apply-templates />
</xsl:template>

<xsl:template match="courses-component">
  <xsl:if test="position()=1">
    ..(do some outputting for the first element here)...
  </xsl:if>

  ...(rest of my XSL template here)...

</xsl:template>

</xsl:stylesheet>

Now here's the catch, I cannot use two different <xsl:templates> with one XPATH being "/page-components/courses-component" and the other being "/page-components/courses-components[1]" (unless I absolutely must, but I don't like coding twice if I can avoid it). Also, I don't have the ability to change the <xsl:apply-templates>, so I cannot do <xsl:apply-templates select="/page-components/courses-components[1]">. Does anyone know of another solution?

Thank you,
Henry

Reply By: mhkay Reply Date: 4/17/2008 8:14:20 AM
Rather than saying you have lots of problems, it's useful to say what your problems are.

Unless you're using a processor such as Microsoft or Altova which removes the whitespace text nodes, the first courses-component element is the second node, so it satisfies position()=2. I would change <xsl:apply-templates/> to <xsl:apply-templates select="*"/> to fix this. You say you can't do that, but you haven't said why.

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
Reply By: humansky Reply Date: 4/17/2008 8:25:00 AM
Michael,
Thank you for the quick response. I apologize for being so unclear. I don't have access to the <xsl:apply-templates /> because that is located in another file that I do not have edit rights to. I only have edit rights for the <courses-component /> element file that is being imported by the another file (the root file).

Also, I forgot to mention, that there can be one or more <courses-component /> as well as any other elements, such as <foo-component />, and there is no set position for any of these components. <courses-component /> can be first or <foo-component /> can be first, therefore checking position()=2 will not work.

Reply By: samjudson Reply Date: 4/17/2008 8:37:15 AM
Well that kinda changes the question a bit doesn't it.

Try:

<xsl:if test="not(preceding-sibling::courses-component)">
 <!-- first course component -->
</xsl:if>

or something like that. Obviously this will take longer the more course-component elements you have.

/- Sam Judson : Wrox Technical Editor -/
Reply By: mhkay Reply Date: 4/17/2008 8:39:05 AM
Then you could try

<xsl:if test="not(preceding-sibling::courses-component)">

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
Reply By: humansky Reply Date: 4/17/2008 8:46:24 AM
Thank you Sam and Michael, that did the trick.



Go to topic 70678

Return to index page 1