Unable to understand this xquery function - xquery

I am new to xquery and unable to understand what does it means :
declare function my:get-unique-lines($object)
{
let $lines := distinct-values (
for $line in $object[contains(#name," ")]/#name
return (string-join(tokenize($line," ")[position()< last()]," "))
)
return $lines
};

Well firstly, the variable $lines is obviously redundant. We're left with
distinct-values (
for $line in $object[contains(#name," ")]/#name
return (string-join(tokenize($line," ")[position()< last()]," "))
What string-join(tokenize($line," ")[position()< last()] does is to split $line into tokens at space boundaries, take all tokens except the last, and then join them back together with space as a separator.
We do that for all the selected #name values, and then remove duplicates.
So if $object contains a list of element like
<e name="John Smith"/>
<e name="John Jones"/>
<e name="John Henry Jones"/>
<e name="John Henry Miller"/>
the result will be the two strings "John" and "John Henry".

Related

PHP's explode() is not working on hyphen-minus -

I am try to use explode() on a string fetched from a database but it didn't work. I have tried explode('-',$string) but it's still not working.
Here is my string which I want to explode:
Expression of Interest – Join our Paint Team – North
If you look closely the hyphen from the string is not the same as the hyphen you use as your argument for the explode.
The hyphen in the string is the following – while the hyphen you pass as the argument for explode() is -. As you can see they don't match (the one in the string is longer than the one you try to compare it with). Because the characters don't match, the explode function is returning the whole string.
<?php
$string = "Expression of Interest – Join our Paint Team – North";
$strings = explode('–', $string);
var_dump($strings);
I have copied the hyphen from the text and used that as an argument for explode() and it works fine.
Might be $string is not string, you can use strval( $string ) to convert it to string i.e. explode('–', strval ( $string ) );
$eString = explode('–', strval ( $string ) );
// vardump($eString) - Now it is an array.
// echo $eString[0];
I have fix the issue by trying this
$post_job_title = htmlentities(get_the_title($posts));
$post_job_title = explode (" – ", $post_job_title);

How to match space in MarkLogic using CTS functions?

I need to search those elements who have space " " in their attributes.
For example:
<unit href="http:xxxx/unit/2 ">
Suppose above code have space in the last for href attribute.
I have done this using FLOWER query. But I need this to be done using CTS functions. Please suggest.
For FLOWER query I have tried this:
let $x := (
for $d in doc()
order by $d//id
return
for $attribute in data($d//#href)
return
if (fn:contains($attribute," ")) then
<td>{(concat( "id = " , $d//id) ,", data =", $attribute)}</td>
else ()
)
return <tr>{$x}</tr>
This is working fine.
For CTS I have tried
let $query :=
cts:element-attribute-value-query(xs:QName("methodology"),
xs:QName("href"),
xs:string(" "),
"wildcarded")
let $search := cts:search(doc(), $query)
return fn:count($search)
Your query is looking for " " to be the entirety of the value of the attribute. If you want to look for attributes that contain a space, then you need to use wildcards. However, since there is no indexing of whitespace except for exact value queries (which are by definition not wildcarded), you are not going to get a lot of index support for that query, so you'll need to run this as a filtered search (which you have in your code above) with a lot of false positives.
You may be better off creating a string range index on the attribute and doing value-match on that.

Conditionally creating formatted string from elements and attributes in XQuery

I'm trying to convert an xml document into a specific tab separated flat file structure. Most of the elements can be mapped to single columns or concatenated simply using fn:string-join(), but I have some elements where the mapping is more complicated. An example element looks like this:
<record>
<details>
<passports>
<passport country="">0018061/104</passport>
<passport country="UK">0354761445</passport>
<passport country="USA">M001806145</passport>
</passports>
</details>
<record>
and I need to create a column that looks like this:
0018061/104;(UK) 0354761445;(USA) M001806145
so if the #country attribute is not "" it is put in (), otherwise it is omitted. The element value follows and each element is separated by ;.
Here's what I have done so far:
for $record in //record
return concat($record/#uid/string(),
(: ... other columns ... :)
" ", <S>{for $r in //$record/details/passports/passport
return concat("(", $r/#country, ") ", $r, ";")}</S>/string()
,"
")
I'm sure there's an easier way, but this almost does the job - it produces:
() 0018061/104;(UK) 0354761445;(USA) M001806145
Ideally I'd like to know the correct way to do this, otherwise just removing the empty brackets where #country="" would suffice.
Use an if clause right in the outer concat (I added some newlines for better readability in the answer, you can of course remove them as you wish):
concat(
if ($r/#country != "")
then concat("(", $r/#country, ") ")
else "",
$r,
";"
)
New result of the query:
0018061/104; (UK) 0354761445; (USA) M001806145;
You could also go for an implicit loop
/record/details/passports/passport/string-join(
(
" ",
if (#country != "")
then "(" || #country || ") "
else (),
.
), ""
)
or explicitly loop over the results and still have a cleaner query (by replacing the concatenation operator || by respective concat(...) calls, you would stay XQuery 1.0 compatible):
for $record in /record/details/passports/passport
return (
" " || (
if ($record/#country != "")
then "(" || $record/#country || ") "
else ()
) || $record
)
Both cases use the implicit newlines inserted by BaseX in-between tokens, alternatively you can of course add them as you had before.

XQuery "flattening" an element

I am extracting data from an XML file and I need to extract a delimited list of sub-elements. I have the following:
for $record in //record
let $person := $record/person/names
return concat($record/#uid/string()
,",", $record/#category/string()
,",", $person/first_name
,",", $person/last_name
,",", $record/details/citizenships
,"
")
The element "citizenships" contains sub-elements called "citizenship" and as the query stands it sticks them all together in one string, e.g. "UKFrance". I need to keep them in one string but separate them, e.g. "UK|France".
Thanks in advance for any help!
fn:string-join($arg1 as xs:string*, $arg2 as xs:string) is what you're looking for here.
In your currently desired usage, that would look something like the following:
fn:string-join($record/details/citizenships/citizenship, "|")
Testing outside your document, with:
fn:string-join(("UK", "France"), "|")
...returns:
UK|France
Notably, ("UK", "France") is a sequence of strings, just as a query returning multiple citizenships would likewise be a sequence (the entries in which will be evaluated for their string value when passed to fn:string-join(), which is typed as taking a sequence of strings for its first argument).
Consider the following (simplified) query:
declare context item := document { <root>
<record uid="1">
<person>
<citizenships>
<citizenship>France</citizenship>
<citizenship>UK</citizenship>
</citizenships>
</person>
</record>
</root> };
for $record in //record
return concat(fn:string-join($record//citizenship, "|"), "
")
...and its output:
France|UK

array count doesn't show correct number, rather just "1"

I have several John Jones with different names in a form. I submit the form to another program which uses "$checkednames = implode(', ', $_POST['raters']);". I echo $checkednames and see all the names but "count($checkednames)" is 1 and not the number of names. What could be wrong?
I appreciate any help.
You may seen the results by going to:
www.golfcourseratingassistant.org/ratecourse/
select Course name > Select Tee Box > Course Data ...select for all lists then "Save Data".
Selected data is only valid for the current session.
It will be 1 only, implode() returns a string containing a string representation of all the array elements in the same order, with the glue string between each element. See Manual
explode() will return an array of strings
So count() after explode() will give you the number of elements.
You can see the names because it is one string.
$array = array('lastname', 'email', 'phone');
$comma_separated = implode(",", $array);
echo count($comma_separated);// Output will be 1
For explode():
$string= "lastname,email,phone";
$array= explode(",", $string);
echo count($array); //output will be 3

Resources