Re: [xsl] Template matching attribute

Subject: Re: [xsl] Template matching attribute
From: Peter Davis <pdavis152@xxxxxxxxx>
Date: Fri, 6 Sep 2002 00:30:30 -0700
On Thursday 05 September 2002 22:36, Kalyan Kumar Mudumbai wrote:
> I am merging two files, and I have an element in
> file 1 like this.
>
> <Currency Unit="DOL">50</Currency>
>
> and in file 2 I have an element:
>
> <Unit key="DOL" val="$"/>
>
> In the output I should get it as:
>
> <Currency Unit="$">50</Currency>

I would normally suggest that you use <xsl:key> to easily look up the 
key/value pairs, but it is difficult (although not impossible) to adapt that 
to this usage since the keys and values are stored in another document, and 
since it sounds like the key names aren't known beforehand.  So, I'll try to 
suggest something else.  It's untested:

[I left out the 'xsl:' prefix on all of the elements below, but the meaning 
stays the same.]

The first step is to load the second document and store it in a variable:

<variable name="keys" select="document('keys.xml')"/>

And since you're copying everything but the attributes verbatim, the second 
step is to write a basic identity template:

<template match="node()">
  <copy>
    <apply-templates select="@*"/>
    <apply-templates/>
  </copy>
</template>

Now, you can write one or more templates to copy the attributes with their 
modified values.  If you know the list of attributes that need to be modified 
beforehand, you can write them all out manually like this:

<template match="@Unit">
  <attribute name="Unit">
    <!-- with this usage, you could easily use <xsl:key> here instead,
      bearing in mind that you'd have to use <xsl:for-each> to switch the
      current document; there are a number of other threads on how to use the
      key() function with multiple input documents -->
    <value-of select="$keys//Unit[@key = current()]/@val"/>
  </attribute>
</template>

If you don't know the attributes and elements beforehand, you can use an 
uglier but more general approach:

<template match="@*">
  <!-- give the new attribute the name and namespace as the original -->
  <attribute name="{name()}" namespace-uri="{namespace-uri()}">
    <!-- look up the new value in $keys, in the element with the same
       name and namespace as the attribute and with @key equal to the
       value of the attribute. -->
    <value-of select="$keys//*[local-name() = local-name(current())]
                      [namespace-uri() = namespace-uri(current())]
                      [@key = current()]/@val"/>
  </attribute>
</template>

Hope that helps!

-- 
Peter Davis

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


Current Thread