kalinma
kalinma

Reputation: 527

xQuery convert string to xhtml

My script builds a string that I need to output to xhtml, but xdmp:unquote() does not seem to like quoted attribute values specifically the quotes. I end up with the quote character entity in the output where that actual quote mark (") should be.

Here is the string:

let $title_opts :=  if ( "M.D." eq $acad_title )
                then
                    '<option selected="SELECTED" value="M.D.">M.D.</option><option value="D.O.">D.O.</option>'
                else if ( "D.O." eq $acad_title ) 
                then
                    '<option value="M.D.">M.D.</option><option selected="SELECTED" value="D.O.">D.O.</option>'
                else
                    '<option value="M.D.">M.D.</option><option value="D.O.">D.O.</option>'

and the output:

return <select name="title" id="title">
            { xdmp:unquote( $title_opts ) }
        </select>

The angle brackets come out fine with xdmp:unquote(), but the quotes do not. How do I get everything to display properly?

Upvotes: 1

Views: 474

Answers (4)

DALDEI
DALDEI

Reputation: 3732

if you are going to fully generate each case you can use the shorter literal xml constructor as all qnames are constant

...

the suggestion to use dynamic constructors is because you can more easily conditionally generate parts of an element resulting in less repetitive code. fully constructing each variant defeats that benifit ... producing the same result but with the most code.

imho dericksons is the most elegant

all variants are functionaly equivilent and should have similar performance

Upvotes: 0

derickson
derickson

Reputation: 305

It appears you are trying to build option elements for xhtml. While I like the XQuery in many of the other solutions provided, I believe the code has too much hard coded. Why not move the work of generating option XHTML elements to a helper function?

declare function local:xhtml-options( $options as xs:string*, $selected as xs:string*) as element(option)* {

    for $option in $options
    return
        element option {
            if($option = $selected) then attribute selected {"SELECTED"} else (),
            attribute value {$option},
            text { $option }
        }

};


local:xhtml-options( ("M.D.", "D.0"), $acad_title )

Upvotes: 1

Jens Erat
Jens Erat

Reputation: 38682

Don't construct XQuery elements as strings. If you need to return multiple top-level elements and cannot wrap them in another element, use sequences.

let $title_opts :=  if ( "M.D." eq $acad_title )
                then
                (
                    <option selected="SELECTED" value="M.D.">M.D.</option>,
                    <option value="D.O.">D.O.</option>
                )
                else if ( "D.O." eq $acad_title ) 
                then
                (
                    <option value="M.D.">M.D.</option>,
                    <option selected="SELECTED" value="D.O.">D.O.</option>
                )
                else
                (
                    <option value="M.D.">M.D.</option>,
                    <option value="D.O.">D.O.</option>
                )

Better use a switch-statement anyway:

let $title_opts := switch ($acad_title) 
    case "M.D." return
        (
            <option selected="SELECTED" value="M.D.">M.D.</option>,
            <option value="D.O.">D.O.</option>
        )
    case "D.O." return
        (
            <option value="M.D.">M.D.</option>,
            <option selected="SELECTED" value="D.O.">D.O.</option>
        )   
    default return
        (
            <option value="M.D.">M.D.</option>,
            <option value="D.O.">D.O.</option>
        )

Or if you use element constructors, only add the attribute as needed.

let $title_opts :=
    (
        element { "option" } {
            if ( "M.D." eq $acad_title )
            then attribute { "selected" } {"selected" }
            else (),
            attribute { "value" } { "M.D." },
            "M.D."
        },
        element { "option" } {
            if ( "D.O." eq $acad_title )
            then attribute { "selected" } {"selected" }
            else (),
            attribute { "value" } { "D.O." },
            "D.O."
        }
    )

Upvotes: 3

kalinma
kalinma

Reputation: 527

OK, so it looks like I have to build my options as a select element, not a string:

let $title_opts :=  if ( "M.D." eq $acad_title )
                then
                    element select {
                        attribute name {"title"}, 
                        attribute id {"title"}, 
                        element option {
                            attribute selected {"SELECTED"},
                            attribute value {"M.D."},
                            "M.D."
                        }, 
                        element option {
                            attribute value {"D.O."},
                            "D.O."
                        }
                    }
                else if ( "D.O." eq $acad_title ) 
                then
                    element select {
                        attribute name {"title"}, 
                        attribute id {"title"}, 
                        element option {
                            attribute value {"M.D."},
                            "M.D."
                        }, 
                        element option {
                            attribute selected {"SELECTED"},
                            attribute value {"D.O."},
                            "D.O."
                        }
                    }
                else
                    element select {
                        attribute name {"title"}, 
                        attribute id {"title"}, 
                        element option {
                            attribute value {"M.D."},
                            "M.D."
                        }, 
                        element option {
                            attribute value {"D.O."},
                            "D.O."
                        }
                    }

return { $title_opts }

Upvotes: 0

Related Questions