Reputation: 186
Assume I have the following snippet
<persName>
<forename>Gaius</forename>
<surname>Iulius</surname>
<addName>Caesar</addName>
</persName>
I need a result like [surname], [forename]
where the comma should only be present if necessary.
In XSLT, I'd simply use
<xsl:value-of select="surname" />
<xsl:if test="surname and forename"><xsl:text>, </xsl:text></xsl:if>
<xsl:value-of select="forename" />
Now I naively thought I could transfer this to XQuery – and failed. I was slightly puzzled that
if ($node/forename) then "1" else "0"
if ($node/surname) then "1" else "0"
if ($node/surname and $node/forename) then "1" else "0"
will give 1
, 1
, 0
, respectively.
I worked around this by counting the number of children in one of these cases but I'm still puzzled why this is the way it is.
Tanks for any input!
Edit: here's the code I've been using:
declare function habe:shortName($node) {
<span>{
if ($node/tei:name) then $node/tei:name
else
let $tr := if ($node/tei:surname and count($node/tei:forename)>0) then ", " else ""
return concat($node/tei:surname, $tr, $node/tei:forename)
}</span>
};
which, when given the above snippet, returned IuliusGaius
.
I then tried the three tests above and got the stated result.
I'm doing this on eXist – maybe their implementation is faulty?
Edit: Thanks to @MichaelKay and @joewiz for hinting at misleading typos!
Upvotes: 1
Views: 54
Reputation: 4241
One solution to your original problem (adding a ', '
if both forename
and surname
exist) is to use string-join($strs as xs:string*, $joiner as xs:string)
instead of concat($string as xs:string[...])
:
let $name :=
<persName>
<forename>Gaius</forename>
<surname>Iulius</surname>
<addName>Caesar</addName>
</persName>
return string-join(($name/surname, $name/forename), ', ')
This returns Iulius, Gaius
.
You can also check for presence of nodes directly in boolean expressions:
let $name :=
<persName>
<forename>Gaius</forename>
<surname>Iulius</surname>
<addName>Caesar</addName>
</persName>
return (
$name/surname and $name/forename,
$name/surname and $name/foo
)
This returns true false
.
Upvotes: 1
Reputation: 5294
The following code returns the expected results, (1, 1, 1)
, using eXide on http://exist-db.org/exist/apps/eXide/index.html:
xquery version "3.0";
let $node :=
<persName>
<forename>Gaius</forename>
<surname>Iulius</surname>
<addName>Caesar</addName>
</persName>
return
(
if ($node/forename) then "1" else "0",
if ($node/surname) then "1" else "0",
if ($node/surname and $node/forename) then "1" else "0"
)
Upvotes: 2