[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: Newbie needs xsl

Subject: Re: Newbie needs xsl
From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx>
Date: Thu, 22 Feb 2001 22:25:59 +0000
substring before with space xsl
Hi Rosh,

> Thanks, this has been a tutorial for me. A question in line with
> this scenario - how do you propose applying templates if an
> element (office) forms sub-node as given below?

The template I showed you before was:

<xsl:template match="customer_name">
   <!-- Customer Name -->
   <xsl:text>Customer Name: </xsl:text><xsl:value-of select="@id" />
   <!-- Revenue -->
   <xsl:text>&#xA;   Revenue: $</xsl:text>
   <xsl:value-of select="@revenue div 100" />
   <!-- Office 1 -->
   <xsl:text>&#xA;   Office1: </xsl:text>
   <xsl:value-of select="substring-before(@office1, ' ')" />
   <xsl:text>sq feet</xsl:text>
   <!-- Office 2 -->
   <xsl:if test="@office2">
      <xsl:text>&#xA;   Office2: </xsl:text>
      <xsl:value-of select="substring-before(@office2, ' ')" />
      <xsl:text>sq feet</xsl:text>
   </xsl:if>
   <!-- More Customers -->
   <xsl:apply-templates />
</xsl:template>

This assumed that the size of Office1 and Office2 were stored as
attributes on the customer_name element, so it accessed those values
through the paths:

  @office1
  @office2

Now you have them as children of the customer_name element, so you
need to change the paths that tell the processor how to get the
relevant values. The offices are represented by elements called
'office_name' with their 'id' attribute specifying whether they are
'office1' or 'office2'. The size of each office is stored in the
'space' attribute on the 'office_name' element.

Building a location path is all about thinking about where you're
starting from (the 'customer_name' element) and how you can navigate
through the node tree to get to where you want to go.

The first step in your path is to get the 'office_name' children of
'customer_name' (i.e. of the current node). For that you need the
path:

  office_name

To get 'office1' you want the office_name element whose id attribute
is equal to the string 'office1'.  You use a predicate to filter a set
of nodes to get only the ones you want:

  office_name[@id = 'office1']

Now you've got the relevant 'office_name' element, to get its size,
you want that office_name element's 'space' attribute.  That's another
step:

  office_name[@id = 'office1']/@space

Similarly, you can get the relevant value for office2 through:

  office_name[@id = 'office2']/@space

You need to put these location paths into the original template.  You
also need to change the template so that it only applies templates to
its child customer_name elements - if you don't specify what it should
apply templates to, xsl:apply-templates applies templates to *all*
children of the current node, so it'll apply templates to the
office_name elements as well.

So you need to change the template to:

<xsl:template match="customer_name">
   <!-- Customer Name -->
   <xsl:text>Customer Name: </xsl:text><xsl:value-of select="@id" />
   <!-- Revenue -->
   <xsl:text>&#xA;   Revenue: $</xsl:text>
   <xsl:value-of select="@revenue div 100" />
   <!-- Office 1 -->
   <xsl:text>&#xA;   Office1: </xsl:text>
   <xsl:value-of
      select="substring-before(office_name[@id = 'office1']/@space, ' ')" />
   <xsl:text>sq feet</xsl:text>
   <!-- Office 2 -->
   <xsl:if test="office_name[@id = 'office2']">
      <xsl:text>&#xA;   Office2: </xsl:text>
      <xsl:value-of
         select="substring-before(office_name[@id = 'office2']/@space, ' ')" />
      <xsl:text>sq feet</xsl:text>
   </xsl:if>
   <!-- More Customers -->
   <xsl:apply-templates select="customer_name" />
</xsl:template>

If you want to get those details about the offices through applying
templates instead (which is a good idea if you don't know how many
offices there are going to be), then you can apply templates to all
the office_name elements:

<xsl:template match="customer_name">
   <!-- Customer Name -->
   <xsl:text>Customer Name: </xsl:text><xsl:value-of select="@id" />
   <!-- Revenue -->
   <xsl:text>&#xA;   Revenue: $</xsl:text>
   <xsl:value-of select="@revenue div 100" />
   <!-- Offices -->
   <xsl:apply-templates select="office_name" />
   <!-- More Customers -->
   <xsl:apply-templates select="customer_name" />
</xsl:template>

And then create a template for the office_name elements that gives the
relevant output:

<xsl:template match="office_name">
   <xsl:text>&#xA;   </xsl:text>
   <xsl:value-of select="@id" />
   <xsl:text>: </xsl:text>
   <xsl:value-of
      select="substring-before(@space, ' ')" />
   <xsl:text>sq feet</xsl:text>
</xsl:template>

> The reason I am asking is that xerces complained on an attempt to
> apply-template again when the name matches "office_name" saying that
> apply-template can be used only once in one match (namely
> customer_name). Alternate attempt to call-template also did not
> work.

It would be a lot easier to work out what was wrong in your code if
you showed us what it looked like.  Perhaps you've got an
xsl:apply-templates element within another xsl:apply-templates element
or something?

[By the way, your XML as shown still isn't well formed - you've got
attributes in the end tags of the elements.]

I hope that helps,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/



 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.