Hello,
How to add/replace a complete node in a node tree, with done by a function and by according function parameters. That means with flexible instructions.
Such as:
declare function local:NodeAdd($XML, $XMLPath, $XMLValue) { ?? };
let $XML := <root><xml>text</xml></root> let $XMLAdd := <B>BBB</B> let $XMLPath := $XML/xml
return local:NodeAdd($XML, $XMLPath , $XMLAdd)
Problem: Following examples didn't work, because an internal reference to copy-XML-structure is needed/forced.
example 1: copy / modify
declare function local:NodeAdd($XML, $XMLPath, $XMLValue) {
copy $XML2 := $XML modify ( insert node $XMLValue into $XML2/xml ) return $XML2 };
But: Instead of into $XML2/xml,
into $XML/xml is needed, respectively into $XMLPath
Thanks a lot Michael
Hi Michael,
Please note that an expression will always be evaluated before its result will be bound to a variable.
You didn’t mention what result you would expect. I guess it should be as follows:
<root><xml>text<B>BBB</B></xml></root>
You could pass on a path string to your function and navigate through the single steps, e.g. with fold-left [1]:
declare function local:node-add($xml, $path, $value) { copy $copy := $xml modify ( let $target := fold-left( tokenize($path, '/'), $copy, function($node, $step) { $node/*[name() = $step] } ) return insert node $value into $target ) return $copy };
local:node-add( <root><xml>text</xml></root>, 'xml', <B>BBB</B> )
If you need more flexibility, you can pass on a function that takes care of the navigation inside the copy/modify or update expression:
declare function local:node-add($xml, $target, $value) { $xml update { insert node $value into $target(.) } }; local:node-add( document { <A><B/></A> }, function($n) { $n/A/B }, <C/> )
Best, Christian
[1] http://docs.basex.org/wiki/Higher-Order_Functions#fn:fold-left
On Sun, Oct 29, 2017 at 4:34 PM, michael4you@arcor.de wrote:
Hello,
How to add/replace a complete node in a node tree, with done by a function and by according function parameters. That means with flexible instructions.
Such as:
declare function local:NodeAdd($XML, $XMLPath, $XMLValue) { ?? };
let $XML := <root><xml>text</xml></root> let $XMLAdd := <B>BBB</B> let $XMLPath := $XML/xml
return local:NodeAdd($XML, $XMLPath , $XMLAdd)
Problem: Following examples didn't work, because an internal reference to copy-XML-structure is needed/forced.
example 1: copy / modify
declare function local:NodeAdd($XML, $XMLPath, $XMLValue) {
copy $XML2 := $XML modify ( insert node $XMLValue into $XML2/xml ) return $XML2 };
But: Instead of into $XML2/xml,
into $XML/xml is needed, respectively into $XMLPath
Thanks a lot Michael
Hello Christian,
Thank you very much. This is exactly the requested solution. A little complicate to understand at present, but it works fine.
In BaseX Documentation 8.5.2, Chapter "Context Item" shows more information for that.
Manipulation of an XML structure .... with flexible declare function ....
If there are some similar issues or solutions in BaseX community, this will be very interesting. Any other sources to learn more about?
Many thanks Michael
Christian Grün hat am 29. Oktober 2017 um 17:10 geschrieben:
Hi Michael, Please note that an expression will always be evaluated before its result will be bound to a variable. You didn’t mention what result you would expect. I guess it should be as follows: textBBB You could pass on a path string to your function and navigate through the single steps, e.g. with fold-left [1]: declare function local:node-add($xml, $path, $value) { copy $copy := $xml modify ( let $target := fold-left( tokenize($path, '/'), $copy, function($node, $step) { $node/*[name() = $step] } ) return insert node $value into $target ) return $copy }; local:node-add( text, 'xml', BBB ) If you need more flexibility, you can pass on a function that takes care of the navigation inside the copy/modify or update expression: declare function local:node-add($xml, $target, $value) { $xml update { insert node $value into $target(.) } }; local:node-add( document { }, function($n) { $n/A/B }, ) Best, Christian [1] http://docs.basex.org/wiki/Higher-Order_Functions#fn:fold-left On Sun, Oct 29, 2017 at 4:34 PM, wrote: > > Hello,
How to add/replace a complete node in a node tree, with done by a function and by according function parameters. That means with flexible instructions. Such as: declare function local:NodeAdd($XML, $XMLPath, $XMLValue) { ?? }; let $XML := text let $XMLAdd := BBB let $XMLPath := $XML/xml return local:NodeAdd($XML, $XMLPath , $XMLAdd) Problem: Following examples didn't work, because an internal reference to copy-XML-structure is needed/forced. example 1: copy / modify declare function local:NodeAdd($XML, $XMLPath, $XMLValue) { copy $XML2 := $XML modify ( insert node $XMLValue into $XML2/xml ) return $XML2 }; But: Instead of into $XML2/xml, into $XML/xml is needed, respectively into $XMLPath Thanks a lot Michael >
Hi Michael,
Manipulation of an XML structure .... with flexible declare function ....
If there are some similar issues or solutions in BaseX community, this will be very interesting. Any other sources to learn more about?
You can have a look at the lecture slides that are listed at [1], in particular “XQuery: More than Just a Query Language”. Our documentation contains various practical XQuery examples as well (see e.g. [2]). The 2nd edition of Priscilla Walmsley’s book is one of the best available printed resources [3]. It was published end of 2015, so it includes all new features of XQuery 3 and XQuery 3.1.
It takes a while and efforts to explore the full complexity and variety of the XQuery language, but may save you a lot of time in the long term.
Christian
[1] http://phobos103.inf.uni-konstanz.de/xml15 [2] http://docs.basex.org/wiki/Update [3] http://shop.oreilly.com/product/0636920035589.do
Christian Grün hat am 29. Oktober 2017 um 17:10 geschrieben:
Hi Michael,
Please note that an expression will always be evaluated before its result will be bound to a variable.
You didn’t mention what result you would expect. I guess it should be as follows:
textBBB
You could pass on a path string to your function and navigate through the single steps, e.g. with fold-left [1]:
declare function local:node-add($xml, $path, $value) { copy $copy := $xml modify ( let $target := fold-left( tokenize($path, '/'), $copy, function($node, $step) { $node/*[name() = $step] } ) return insert node $value into $target ) return $copy };
local:node-add( text, 'xml', BBB )
If you need more flexibility, you can pass on a function that takes care of the navigation inside the copy/modify or update expression:
declare function local:node-add($xml, $target, $value) { $xml update { insert node $value into $target(.) } }; local:node-add( document { }, function($n) { $n/A/B },
)
Best, Christian
[1] http://docs.basex.org/wiki/Higher-Order_Functions#fn:fold-left
On Sun, Oct 29, 2017 at 4:34 PM, wrote:
Hello,
How to add/replace a complete node in a node tree, with done by a function and by according function parameters. That means with flexible instructions.
Such as:
declare function local:NodeAdd($XML, $XMLPath, $XMLValue) { ?? };
let $XML := text let $XMLAdd := BBB let $XMLPath := $XML/xml
return local:NodeAdd($XML, $XMLPath , $XMLAdd)
Problem: Following examples didn't work, because an internal reference to copy-XML-structure is needed/forced.
example 1: copy / modify
declare function local:NodeAdd($XML, $XMLPath, $XMLValue) {
copy $XML2 := $XML modify ( insert node $XMLValue into $XML2/xml ) return $XML2 };
But: Instead of into $XML2/xml,
into $XML/xml is needed, respectively into $XMLPath
Thanks a lot Michael
basex-talk@mailman.uni-konstanz.de