[xquery-talk] renaming single attributes
Howard Katz
howardk at fatdog.com
Mon Jun 20 14:01:12 PDT 2005
> -----Original Message-----
> From: Michael Kay [mailto:mhk at mhk.me.uk]
> > What's the easiest and/or most concise way of effecting a
> > transformation that renames a single named attribute, if
> present, and
> > leaves everything else the same? For example, I might
> want to rename
> > every occurrence of
> > @att3 (two instances below) as @NEW-att3. Here's some
> sample "before"
> > data:
> >
> > <record att1="att1" att3="att3" att4="att4">content1</record>
> > <record att3="att3" att4="att4">content2</record>
> > <record att4="att4" att5="att5">content3</record>
> >
> > Here's the "after" version of the same. Note that all nodes except
> > @att3 remains the same:
> >
> > <record att1="att1" NEW-att3="att3"
> att4="att4">content1</record>
> > <record NEW-att3="att3" att4="att4">content2</record>
> > <record att4="att4" att5="att5">content3</record>
> >
> > What's the simplest document tranformation that will
> accomplish this
> > goal?
>
> This probably isn't the solution you were looking for, but:
>
> <xsl:template match="node()|@*">
> <xsl:copy><xsl:apply-templates
> select="node()|@*"/></xsl:copy> </xsl:template>
>
> <xsl:template match="@att3">
> <xsl:attribute name="NEW-att3"><xsl:value-of
> select="."/></xsl:attribute> </xsl:template>
>
> If you add the constraint that you want an XQuery solution,
> then (in the absence of an update facility) you essentially
> have to simulate the same kind of recursive descent, copying
> everything except the one thing you want to change. It's
> just a bit more tedious without apply-templates:
Yes, I was primarily interested in an XQuery solution. (Given the name of
the list, I didn't think I'd need to specify that.) Nevertheless I'm glad
you provided this code snippet since it raises one interesting question. Why
do the match and select attributes have a unioned value of "node() | @*"?
Doesn't the first term of the union subsume the second?
> declare function f:identity($n as node()) {
> typeswitch ($n)
> case element() as $e return
> element {node-name($e)}
> {$e/(@* except @att3),
> if (@att3) then attribute {"NEW-att3"}
> {string(@att3)} else (),
> for $c in $e/node() return f:identity($c)
> }
> case comment() as $c return $c
> case processing-instruction() as $p return $p
> case text() as $t return $t
> }
Hmm, I'm having to go slow to parse the bit of code you've got packed into
the "case element() as $e" clause. Thanks -- seriously! -- for that bit of a
mental workout. I also hadn't seen "except" used in exactly that way before.
That's a much more natural usage than "intersect" in this particular
instance.
> - and you lose any namespace nodes because there's no way of
> copying them.
>
> This kind of thing would become much easier in XQuery with
> higher-order functions. One could then have a standard
> tree-walking function that applies a supplied function to
> each node. Something like this:
>
> declare function f:rename-att3($n as node()) {
> if ($n instance of attribute(att3))
> then attribute {"NEW-att3"} {string($n)}
> else $n
> }
>
> tree-walk(/, f:rename-att3)
That would indeed be very nice.
>
> Michael Kay
> http://www.saxonica.com/
>
>
More information about the talk
mailing list