Search code examples
xquery

How do I call a function in xquery


Xml format is like:

<outer_element>
    <list>
     <leaf name="abc">
                  <D:a value=""/>
                  <D:b value="2"/>
                  <D:c value="3"/>
                  <D:text_enabled value="true"/>
         </leaf>


     <leaf name="xyz">
      ....
     </leaf>
</list>
</outer_element>

This is just the structure, below is the xquery for removing certain portion of the xml: to remove leafs that have D:text_enabled value="true"

declare namespace my="my.uri"; 
declare variable $flag;

declare function my:isEnabled($node as node()) as xs:boolean
{
   let $flag :=
    for $child in $node/node()
    return string-join(if(name($child) eq "D:text_enabled" and $child/@value eq "true") then "true" else "false" , " ")

    return contains($flag,"true")


};

declare function my:filtering($node as node()) 
{  
  typeswitch ($node)

    case element() 

      return
      
        if (string(local-name($node)) = "import")
        then
          ()
        else

        if(string(local-name($node)) = "leaf" and $flag=isEnabled($node) )
        then
          ()
        else
        element
            {
            node-name($node)
            }           {
             $node/@*
           ,
           for $child in $node/node()
              return my:filtering($child )
 
          }
    default 
      return
      if (string(local-name($node)) = "import")
      then
        ()
      else
        $node
};

let $input := doc("input.xml")

return
  for $elem in $input/*
  return
    my:filtering($elem)

Errors I am getting are:

XPST0003: XQuery syntax error in #...eclare variable $flag; declare#: Expected ':=' or 'external' in variable declaration XPST0008: XQuery static error in #... = "leaf" and $flag=isEnabled#: Variable $flag has not been declared Static error(s) in query


Solution

  • This is nothing to do with calling a function.

    A global variable must either be declared external, in which case a value is supplied by the calling application:

    declare variable $flag external;
    

    or it must be initialised to a value:

    declare variable $flag := false();
    

    But actually, you're not using the global variable at all, so you can just delete the declaration. You've got another quite separate local variable called $flag, that doesn't need a global declaration.

    Some further suggestions:

    • if (string(local-name($node)) = "import") is better written as `if ($node[self::*:import])

    • As far as I can tell, the code

    let $flag := for $child in $node/node() return string-join(if(name($child) eq "D:text_enabled" and $child/@value eq "true") then "true" else "false" , " ")
    return contains($flag,"true")

    can probably be written as

    exists($node/D:text_enabled[@value eq "true"])