How can we update a value in xquery other than node-replace? I have an element called title which is empty , I should be updating the value as “submitted”. Sample file:
<books>
<title></title>
</books>
How can we update a value in xquery other than node-replace? I have an element called title which is empty , I should be updating the value as “submitted”. Sample file:
<books>
<title></title>
</books>
I assume you are asking for an alternative to xdmp:node-replace() because this XML doc is an in-memory object and not (yet) a persisted document?
You could perform a recursive descent typeswitch
xquery version "1.0-ml";
(: This is the recursive typeswitch function :)
declare function local:transform($nodes as node()*) as node()*
{
for $n in $nodes return
typeswitch ($n)
case text() return $n
case attribute() return $n
case comment() return $n
case processing-instruction() return $n
case element (title) return <title>submitted</title>
default return element {$n/name()} {local:transform($n/(@*|node()))}
};
let $books :=
<books foo="x"><!--test--><?PITarget PIContent?>
<title></title>
</books>
return
local:transform($books)
, but I find that to be tedious and don't like for general purpose transformations if you wind up needing more complex transformation scenarios.
For more complicated transformations of in-memory XML structures in XQuery, then I would look to use Ryan Dew's XQuery XML Memory Operations library:
import module namespace mem = "http://maxdewpoint.blogspot.com/memory-operations"
at "/memory-operations.xqy";
let $books :=
<books>
<title></title>
</books>
return
mem:copy(fn:root($books)) ! (
mem:replace(., $books/title, element title {"submitted"}),
mem:execute(.)
)
When transforming XML (whether in-memory or documents in the database), I prefer XSLT. You could use either xdmp:xslt-invoke() (with an installed stylesheet) or with xdmp:xslt-eval():
xquery version "1.0-ml";
let $xslt :=
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="title">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:text>submitted</xsl:text>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
let $books :=
<books>
<title></title>
</books>
return xdmp:xslt-eval($xslt, $books)