Re: [xsl] sub element selection

Subject: Re: [xsl] sub element selection
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Tue, 16 Apr 2002 18:16:20 +0100
Hi Pete,

> I'm having trouble figuring out how to get the value of
> CommunicationType and then compare it to a string (or should it be a
> variable?). If you see an obviously easier way to do it (xsl:when?
> xsl:for-each?) please let me know.

Since you're on the CommunicationType element at the point where you
want to do the comparison, you can just use . to mean "the value of
the current node":

<xsl:template match="CommunicationType">
  <xsl:if test=". = 'DAYPHONE'">
    ...
  </xsl:if>
  <xsl:if test=". = 'EMAIL'">
    ...
  </xsl:if>
</xsl:template>

although since these two tests are mutually exclusive, you could use
xsl:choose instead:

<xsl:template match="CommunicationType">
  <xsl:choose>
    <xsl:when test=". = 'DAYPHONE'">
      ...
    </xsl:when>
    <xsl:when test=". = 'EMAIL'">
      ...
    </xsl:when>
  </xsl:choose>
</xsl:template>

To pass the value to the 'makeProperty' template, you need to pass the
value of the current CommunicationType element's sibling
CommunicationNumber element. The easiest way to get hold of that is to
go up to the Communication element and then down again to the
CommunicationNumber element:

  parent::Communication/CommunicationNumber

or:

  ../CommunicationNumber

This gives:
  
<xsl:template match="CommunicationType">
  <xsl:choose>
    <xsl:when test=". = 'DAYPHONE'">
      <xsl:call-template name="makeProperty">
        <xsl:with-param name="name">HOMEPHONE</xsl:with-param>
        <xsl:with-param name="value" select="../CommunicationNumber" />
      </xsl:call-template>
    </xsl:when>
    <xsl:when test=". = 'EMAIL'">
      <xsl:call-template name="makeProperty">
        <xsl:with-param name="name">DRV1_EMAIL</xsl:with-param>
        <xsl:with-param name="value" select="../CommunicationNumber" />
      </xsl:call-template>
    </xsl:when>
  </xsl:choose>
</xsl:template>

Personally, I find that getting sibling values usually means that I'm
using a template at the wrong kind of level. In this case it makes
more sense to me to match the Communication elements and refer to the
CommunicationType and CommunicationNumber children as follows:

<xsl:template match="Communication">
  <xsl:choose>
    <xsl:when test="CommunicationType = 'DAYPHONE'">
      <xsl:call-template name="makeProperty">
        <xsl:with-param name="name">HOMEPHONE</xsl:with-param>
        <xsl:with-param name="value" select="CommunicationNumber" />
      </xsl:call-template>
    </xsl:when>
    <xsl:when test="CommunicationType = 'EMAIL'">
      <xsl:call-template name="makeProperty">
        <xsl:with-param name="name">DRV1_EMAIL</xsl:with-param>
        <xsl:with-param name="value" select="CommunicationNumber" />
      </xsl:call-template>
    </xsl:when>
  </xsl:choose>
</xsl:template>

And since you're doing roughly the same for each of them, I'd be
tempted to put the xsl:choose within the xsl:with-param rather than
having two separate calls, although on the other hand this does assume
that the CommunicationType is either 'DAYPHONE' or 'EMAIL', which
might not be a valid assumption:

<xsl:template match="Communication">
  <xsl:call-template name="makeProperty">
    <xsl:with-param name="name">
      <xsl:choose>
        <xsl:when test="CommunicationType = 'DAYPHONE'">HOMEPHONE</xsl:when>
        <xsl:when test="CommunicationType = 'EMAIL'">DRV1_EMAIL</xsl:when>
      </xsl:choose>
    </xsl:with-param>
    <xsl:with-param name="value" select="CommunicationNumber" />
  </xsl:call-template>
</xsl:template>

In your 'makeProperty' template, it would also probably be simpler if
you used attribute value templates rather than xsl:attribute:

<xsl:template name="makeProperty">
  <xsl:param name="name"/>
  <xsl:param name="value"/>
  <property name="{$name}" value="{$value}" />
</xsl:template>

Or of course you could do the whole thing in one template if you
wanted:

<xsl:template match="Communication">
  <property value="{CommunicationNumber}">
    <xsl:attribute name="name">
      <xsl:choose>
        <xsl:when test="CommunicationType = 'DAYPHONE'">HOMEPHONE</xsl:when>
        <xsl:when test="CommunicationType = 'EMAIL'">DRV1_EMAIL</xsl:when>
      </xsl:choose>
    </xsl:attribute>
  </property>
</xsl:template>

---

In XSLT 2.0, even simpler:

<xsl:template match="Communication">
  <property name="{if (CommunicationType = 'DAYPHONE') then 'HOMEPHONE'
                   else if (CommunicationType = 'EMAIL') then 'EMAIL'}"
            value="{CommunicationNumber}" />
</xsl:template>

Cheers,

Jeni

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


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


Current Thread