Flexible update via function

Sunday, 29 October 2017 · 4 messages · last reply 1 Nov 2017
M
michael4you29 Oct 2017 16:34 #
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
CG
Christian Grün29 Oct 2017 17:10 #
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/>
  )
Quoted text · michael4you · 46 lines
On Sun, Oct 29, 2017 at 4:34 PM, <michael4you at 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
MB
Michael Burkert31 Oct 2017 22:57 #
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
Quoted text · Christian Grün · 107 lines
> 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 > > > > >
CG
Christian Grün1 Nov 2017 10:44 #
Hi Michael,
Quoted text · Michael Burkert · 4 lines
> 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
Quoted text · Michael Burkert · 105 lines
> 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

⚡Generated with XQuery