Re: [xsl] Copying unknown attributes in XML to XML transformation?

Subject: Re: [xsl] Copying unknown attributes in XML to XML transformation?
From: "Bill Burton" <billb@xxxxxxxxxxxx>
Date: Fri, 26 Jan 2001 23:38:53 -0500
Hello,

Jeni Tennison wrote:
> 
> David C. wrote:
> > ] Try this, Bill:
> > ]
> > ] <xsl:template match="connectionFactory">
> > ]   <xsl:element name="connectionFactory">
> > ]     <xsl:for-each select="@*">
> > ]       <xsl:attribute name="{name(.)}"><xsl:value-of select="."/></xsl:attribute>
> > ]     </xsl:for-each>
> > ]    <xsl:attribute name="host"><xsl:value-of select="$host"/></xsl:attribute>
> > ]    <xsl:attribute name="port"><xsl:value-of select="$port"/></xsl:attribute>
> > ]   </xsl:element>
> > ] </xsl:template>
> >
> > That works, but it is equivalent to the rather shorter
> >
> > <xsl:template match="connectionFactory">
> >   <connectionFactory host="{$host}" port="{$port}">
> >   <xsl:copy-of select="@*"/>
> >  </connectionFactory>
> > </xsl:template>
> 
> I think it's not quite equivalent, because of the order in which the
> attributes are added. In the first, any existing 'host' or 'port'
> attributes are added within the xsl:for-each, but then overridden by
> the xsl:attribute instructions that add the values from the variables.
> In the second, the 'host' and 'port' attributes are given values from
> the variables, but then overridden by the attributes copied onto the
> element.

Yes, that's exactly what I found (and had tried orginally).  Thanks for
clarifying this for everybody.

> I think the first *is* equivalent to:
> 
>   <connectionFactory>
>      <xsl:copy-of select="@*" />
>      <xsl:attribute name="host">
>         <xsl:value-of select="$host" />
>      </xsl:attribute>
>      <xsl:attribute name="port">
>         <xsl:value-of select="$port" />
>      </xsl:attribute>
>   </connectionFactory>

Yes, it is.  The above is a little more verbose than the original solution
proposed by a couple of people (below), but I think the syntax is simpler
and if there are more than two or three attributes that need their values
substituted, will be easier to maintain than this solution:

  <xsl:template match="connectionFactory">
    <connectionFactory host="{$host}" port="{$port}">
      <xsl:copy-of select="@*[name()!='host' and name()!='port']"/>
    </connectionFactory>
  </xsl:template>

After a bit of experimentation, I came up with this:
  <xsl:template match="connectionFactory">
    <connectionFactory host="{$host}" port="{$port}">
      <xsl:copy-of select="@*[not(contains('host|port',name()))]"/>
    </connectionFactory>
  </xsl:template>

It still seems rather odd to me that where copying a selected list
attributes (in this case) is so easy with:
  <xsl:copy-of select="@attr1|@attr2|@attr3"/>
that there ought to also be a similarly easy way to copy all nodes except
the specified ones.  Maybe something like:
  <xsl:copy-of select="@*[exclude(@attr1|@attr2|@attr3)]"/>
or
  <xsl:copy-of select="@*" exclude="@attr1|@attr2|@attr3"/>

> Cheers,
> 
> Jeni
> 
> ---
> Jeni Tennison
> http://www.jenitennison.com/

Thanks Jeni and thanks again for everyone's input.

-Bill Burton

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


Current Thread