78795

Xquery: not working case expression in a switch function

I raise this question after multiples tests in order to verify that my expression is correct. And it is, although it still doesn't go through.

I'm using the classic dispatch/passthru function to convert an XML database (with its own schema using the namespace spip) to XML files (with another schema).

declare function p($node as element(spip:p)+, $options as map(*)) { switch ($node) case ( $node/spip:* instance of element(spip:img) and fn:not($node/text()[fn:normalize-space(.) != '']) ) return passthru($node, $options) case ( $node/spip:* instance of element(spip:figure) and fn:not($node/text()[fn:normalize-space(.) != '']) ) return passthru($node, $options) case ( $node/spip:* instance of element(spip:blockquote) and fn:not($node/text()[fn:normalize-space(.) != '']) ) return passthru($node, $options) default return <para> <alinea>{ passthru($node, $options) }</alinea> </para> };

The case expressions basically test the nature of the child element ($node/spip:*) in a <p> element and whether this <p> element contains some text. It works! At least for the childs <blockquote> and <figure>, but it doesn't for the element <img>.

Nodes with that structure <p><img/></p> are going through the default case, whereas nodes like <p><blockquote>xxx</blockquote></p> or <p><figure>xxx</figure></p> are passing the test.

I have tried to be more specific in testing the <img> element with :

case ($node/child::*[1] instance of element(spip:img))

The weird thing is that both tests are working fine in a if then else Expression. Then I have the result I want..

Any suggestion.s for improving the tests and having <p><img/></p> properly treated ?

Answer1:

A <strong>switch</strong> case will atomize the item and compare it's atomized value for equality of the case clause.

In a switch expression, the switch keyword is followed by an expression enclosed in parentheses, called the switch operand expression. This is the expression whose value is being compared.

Similarly, the expression in a typeswitch case clause evaluates the type of node.

Each case clause specifies a SequenceType followed by a return expression.

The reason why your <strong>switch</strong> isn't working the way that you expect is that you are testing both the type and evaluating the content to produce a boolean value, which does not equal the atomized value of the node being tested.

You could move the logic for computing the tested value up into the switch expression being tested in your case statement. For instance, produce a string value that concatenates the namespace-uri(), local-name(), and the value of the text() value

declare function local:p($node as element(spip:p)+, $options) { let $namespace-uri := namespace-uri-from-QName(xs:QName("spip:foo")) (: you could hard-code the namespace-uri as well :) return switch (concat($node/*/namespace-uri(), $node/*/local-name(), $node/text()[normalize-space(.)])) case ( concat($namespace-uri, "img") ) return local:passthru($node, $options) case ( concat($namespace-uri, "figure") ) return local:passthru($node, $options) case ( concat($namespace-uri, "blockquote") ) return local:passthru($node, $options) default return <para> <alinea>{ local:passthru($node, $options) }</alinea> </para> };

However, you should probably just stick with the if then else.

You could combine the criteria in your tests to reduce the number of if/else blocks:

declare function p($node as element(p)+, $options as map(*)) { if ( ( $node/* instance of element(spip:img) or $node/* instance of element(spip:figure) or $node/* instance of element(spip:blockquote) ) and not($node/text()[fn:normalize-space(.)]) ) then local:passthru($node, $options) else <para> <alinea>{ local:passthru($node, $options) }</alinea> </para> };

Recommend

  • Creating in an infinite loop using setTimeout
  • Reset CSS styles for a DIV and all nested elements
  • Trying to get a div w/ 100% height and overflow auto to work in Firefox
  • addEventListener() in Lua
  • Cannot connect to my database from within SQL Management Studio
  • Extracting data from a string where the data structure is embedded in the string itself
  • d3.js - Tree Layout - How can I flip it?
  • Can you restrict a generic to T where T is a trait implemented by Self?
  • Tensorflow not predicting accurate enough results
  • How to ignore a block of code when transpiling with BabelJs?
  • Sorting is not working in jQuery datatables
  • jQuery.fn.load() is deprecated?
  • Output error rate per label / confusion matrix
  • How to process a big array applying a async function for each element in nodejs?
  • DataTables+RequireJS: Cannot read property 'defaults' of undefined
  • How to normalize a database schema
  • How to emulate integrated numeric keypad cursor keys in linux
  • Randomly placing a polygon inside of polygon
  • Ransack search string arrays stored in db
  • jQuery file download plugin
  • Get XML response value with GDataXML
  • SQL Server re-calculate or not?
  • if some function is not optimized does it mean that all functions where it is declared are not optim
  • Why doesn't a local variable live long enough for thread::scoped?
  • Use sed with regex and (
  • Why HTML5 Canvas with a larger size stretch a drawn line?
  • Spray.io: When (not) to use non-blocking route handling?
  • Modifying destination and filename of gulp-svg-sprite
  • MySQL WHERE-condition in procedure ignored
  • Web-crawler for facebook in python
  • GridView Sorting works once only
  • trying to dynamically update Highchart column chart but series undefined
  • python regex in pyparsing
  • Busy indicator not showing up in wpf window [duplicate]
  • costura.fody for a dll that references another dll
  • Observable and ngFor in Angular 2
  • How to Embed XSL into XML
  • UserPrincipal.Current returns apppool on IIS
  • Conditional In-Line CSS for IE and Others?
  • java string with new operator and a literal