Xquery variable not set - xquery

In my Xquery 3.1 module I have imported my " global variables" through a module import, one of which ($globalvar:MSGS) contains an XML document that I generally have no problems accessing through reference to the variable. For example this
$globalvar:MSGS//vocab[#xml:id="warning"]
will return
<vocab xml:id="warning">
<span lang="en">Warning! Your changes (OBJECTID) could not be saved!</span>
<span lang="fr">Attention, vos modifications (OBJECTID) n’ont pas pu être sauvegardées !</span>
</vocab>
But the following is returning an error err:XPDY0002 variable '$msg' is not set pointing to line 7-8:
1. let $collid := $mydoc//collection-id/text()
2. let $errtitle :=
3. <msg-error-title>
4. {
5. let $msg := $globalvar:MSGS/id("warning")/span
6. return
7. <en>{replace($msg[#lang="en"]/text(),"OBJECTID",$collid)}</en>,
8. <fr>{replace($msg[#lang="fr"]/text(),"OBJECTID",$collid)}</fr>
9. }
10. </msg-error-title>
11. return $errtitle
But if I remove the inner let ... return and make direct reference to $globalvar:MSGS like below, there are no errors:
let $collid := $mydoc//collection-id/text()
let $errtitle :=
<msg-error-title>
{
<en>{replace($globalvar:MSGS/id("warning")/span[#lang="en"]/text(),"OBJECTID",$collid)}</en>,
<fr>{replace($globalvar:MSGS/id("warning")/span[#lang="fr"]/text(),"OBJECTID",$collid)}</fr>
}
</msg-error-title>
return $errtitle
I don't understand why $msg isn't set in the first example? Is there an alternative?
added test
let $collid := "FOOID"
let $xml :=
<vocab xml:id="warning">
<span lang="en">Warning! Your changes (OBJECTID) could not be saved!</span>
<span lang="fr">Attention, vos modifications (OBJECTID) n’ont pas pu être sauvegardées !</span>
</vocab>
let $errtitle :=
<msg-error-title>
{let $msg := $xml/id("warning")/span
return
<en>{replace($msg[#lang="en"]/text(),"OBJECTID",$collid)}</en>,
<fr>{replace($msg[#lang="fr"]/text(),"OBJECTID",$collid)}</fr>
}
</msg-error-title>
return $errtitle

Your test case fails in Saxon with
Static error
XPST0008 Unresolved reference to variable $msg
The problem is that "," doesn't bind as closely as you think, so you need extra parens around the return expression:
return (
<en>{replace($msg[#lang="en"]/text(),"OBJECTID",$collid)}</en>,
<fr>{replace($msg[#lang="fr"]/text(),"OBJECTID",$collid)}</fr>
)

Related

Import data using mlcp, a csv file and transform parse date

I have a csv file. I've managed import these data into MarkLogic using mlcp which then created a xml file in MarkLogic.
Now in csv I have this format "6/29/2013 5:00:00 PM" random in one of the column. How do I use xquery and probably node-replace as a transform function to convert this date into a different format such as "2013-06-29" as MarkLogic default date format?
Any help is appreciated...
I have created transform.xqy and install it on Modules in MLogic. I'm
thinking about using "xdmp:node-replace" to replace the date with expected
format. Or should I go thorugh the csv column by column (How to do?) and
use "castable as xs:dateTime" to determine date value or not. Yet, even
just printing out the content value/uri, always giving me error.
xquery version "1.0-ml";
module namespace example = "http://test.com/example";
(: If the input document is XML, insert #NEWATTR, with the value
: specified in the input parameter. If the input document is not
: XML, leave it as-is.
:)
declare function example:transform(
$content as map:map,
$context as map:map
) as map:map*
{
let $the-doc-uri := map:get($content, "uri")
let $the-doc := map:get($content, "value")
return
trace($the-doc, 'The value of doc is: ')
};
The MarkLogic documentation contains a full example of an MLCP transform:
https://docs.marklogic.com/guide/mlcp/import#id_65640
It shows this example, which adds an attribute to the XML content:
declare function example:transform(
$content as map:map,
$context as map:map
) as map:map*
{
let $attr-value :=
(map:get($context, "transform_param"), "UNDEFINED")[1]
let $the-doc := map:get($content, "value")
return
if (fn:empty($the-doc/element()))
then $content
else
let $root := $the-doc/*
return (
map:put($content, "value",
document {
$root/preceding-sibling::node(),
element {fn:name($root)} {
attribute { fn:QName("", "NEWATTR") } {$attr-value},
$root/#*,
$root/node()
},
$root/following-sibling::node()
}
), $content
)
};
Keep in mind you are supposed to update the "value" property of the $content map:map, and return $content to get your transformation result added to the database. I suggest using a (potentially recursive) typeswitch to identify element nodes, and then adjusting their value accordingly..
HTH!
finally did it.
The thing is I must use mem:node-replace because it is on the fly, on memory. While xdmp:node-replace is when the data is already on MarkLogic.
The rest is as expected I must use format-date and xdmp:parse-dateTime to get date format as required.
Here is some snippets
xquery version "1.0-ml";
module namespace ns_transform = "this_is_my_namespace";
import module namespace mem = "http://xqdev.com/in-mem-update" at "/MarkLogic/appservices/utils/in-mem-update.xqy";
declare variable $ns := "this_is_my_namespace";
declare function ns_transform:transform(
$content as map:map,
$context as map:map
) as map:map*
{
let $doc := map:get($content, "value")
let $format_in := "[M]/[D]/[Y0001] [h01]:[m01]:[s01] [P]"
let $format_out := "[Y0001]-[M01]-[D01]"
let $old_date := $doc/*:root_doc/*:date/text()
let $new_date := format-date(xs:date(xdmp:parse-dateTime($format_in, $old_date)), $format_out)
let $new_doc := mem:node-replace($doc/*:root_doc/*:date,element {fn:QName($ns, "date")}{$new_date})
let $_ := map:put($content, "value", $new_doc)
return $content
};

I have successfully enlisted a user in cohort via core_cohort_add_cohort_members but getting a warning

I have successfuly enlisted a user in moodle cohort using core_cohort_add_cohort_members but i am getting a warning in response.Can anybody help me remoce this warning.
Here is the warning i get.
{"warnings":[]}
Here is my code
$fname = 'core_cohort_add_cohort_members';
/// Paramètres
$member = new stdClass();
$member->cohorttype[type]='id';
$member->cohorttype[value]=2;
$member->usertype[type]='id';
$member->usertype[value]=8;
$members = array($member);
$par = array('members' => $members);
$rest_format = 'json';
$Serve_Url = 'localhost/moodle' . '/webservice/rest/server.php'. '?wstoken=' . '72f102312fff135cbb4a301d9c7839ae' .'&wsfunction='. $fname;
require_once('curl.inc');
$Rest_format = ($rest_format == 'json') ? '&moodlewsrestformat=' . $rest_format : '';
$curl = new curl;
//if rest format == 'xml', then we do not add the param for backward compatibility with Moodle < 2.2
$rep = $curl->post($Serve_Url.$Rest_format, $par);
dpm($rep);
The warnings array is empty in your example reply.
If you want to detect this more verbosely, you can always just json_decode() the reply. You should see an empty array there.
So I think it's working just as you wanted.
Turn the keys into strings i.e
$member->cohorttype["type"]='id';
$member->cohorttype["value"]=2;
$member->usertype["type"]='id';
$member->usertype["value"]=8;
Mainly because newer versions of PHP may cause real exceptions because of
unidentified variables(type and value)
That aside as Sebastian Berm stated empty warnings array means no problem

XQuery transform string into a datetime (exist-db)

I am using XQuery 3.0 for exist-db, and am trying to make the string $value a dateTime object. This is what I've got, but it's not working:
let $value := '"2001-10-18T08:47:00"'
if ($key = 'start_time')
then
element { $key } { xs:dateTime(string(replace($value, '"', ''))) }
It's saying: illegal lexical form for date-time-like value ''. Any ideas?
I'm unable to reproduce the error you're getting with that code - which is incomplete (lacks return and else clauses, doesn't define $key). But paring those issues away, your code runs fine for me, as follows:
let $value := '"2001-10-18T08:47:00"'
return
xs:dateTime(replace($value, '"', ''))
The result:
2001-10-18T08:47:00

How can I create xquery using xml response

The below mentioned is actual xquery.
declare variable $rankCode_DL3UJ :=("CPT","FO","FM");
declare variable $rankCode_DL4UJ :=("CRFO","CL");
declare variable $type :=("DOM","ISH");
declare function local:getboardingPriorityCode($flightType as element(), $rankCode as element()) as xs:string
{
if(data($flightType) = $type) then
'DHD'
else
if(data($rankCode) = $rankCode_DL3UJ) then
'DL3UJ'
else if(data($rankCode) = $rankCode_DL4UJ) then
'DL4UJ'
else
'DL5UJ'
};
declare function local:getPreferredClass($flightType as element(flightCategory:Code)) as xs:string
{
if(data($flightType) = $type) then
'Y'
else
'J'
};
declare function xf:createDeadheadReservationRQ-to- PassengerDetailsRQ($createDeadheadReservationRQ1 as element(ns1:CreateDeadheadReservationRQ),$CreateDeadHeadReservationAdapterSelect RS as element(ns3:RefTickettypeCollection),
$airBookRS as element(flightCategory:GetFlightCategoryRS))
as element(ns2:PassengerDetailsRQ) {
<ns2:PassengerDetailsRQ Version = "2.0.0">
<ns2:SpecialReqDetails>
<ns2:AddRemarkRQ>
<ns2:RemarkInfo>
<ns2:Remark Type = "General">
<ns2:Text>{ data($createDeadheadReservationRQ1/ns1:SpecialRequestDetails/ns1:Remark) }</ns2:Text>
</ns2:Remark>
</ns2:RemarkInfo>
</ns2:AddRemarkRQ>
<ns2:SpecialServiceRQ>
<ns2:SpecialServiceInfo>
<ns2:SecureFlight SegmentNumber = "A" SSR_Code = "DOCS">
<ns2:PersonName DateOfBirth = "{ data($createDeadheadReservationRQ1/ns1:PassengerInfo/ns1:DateOfBirth) }"
Gender = "{ data($createDeadheadReservationRQ1/ns1:PassengerInfo/ns1:Gender) }"
NameNumber = "1.1">
<ns2:GivenName>{ data($createDeadheadReservationRQ1/ns1:PassengerInfo/ns1:PassengerName/ns1:GivenName) }</ns2:GivenName>
<ns2:Surname>{ data($createDeadheadReservationRQ1/ns1:PassengerInfo/ns1:PassengerName/ns1:Surname) }</ns2:Surname>
</ns2:PersonName>
<ns2:VendorPrefs>
<ns2:Airline Hosted = "true"/>
</ns2:VendorPrefs>
</ns2:SecureFlight>
<ns2:Service SSR_Code = "{ data($createDeadheadReservationRQ1/ns1:SpecialRequestDetails/ns1:RankBasedSSR) }">
<ns2:VendorPrefs>
<ns2:Airline Hosted = "true"/>
</ns2:VendorPrefs>
</ns2:Service>
</ns2:SpecialServiceInfo>
</ns2:SpecialServiceRQ>
</ns2:SpecialReqDetails>
<ns2:TravelItineraryAddInfoRQ>
<ns2:AgencyInfo>
<ns2:Ticketing TicketType = "{fn:concat('7PS-', local:getboardingPriorityCode($airBookRS/flightCategory:ServiceType/flightCategory:Code, $createDeadheadReservationRQ1/ns1:PassengerInfo/ns1:RankCode), local:getPreferredClass($airBookRS/flightCategory:ServiceType/flightCategory:Code))}"/>
</ns2:AgencyInfo>
<ns2:CustomerInfo>
<ns2:PersonName>
<ns2:GivenName>{
xs:string(fn:concat($createDeadheadReservationRQ1/ns1:PassengerInfo/ns1:PassengerName/ns1:GivenName,' ',
$createDeadheadReservationRQ1/ns1:PassengerInfo/ns1:PassengerName/ns1:Title))
}</ns2:GivenName>
<ns2:Surname>{ xs:string($createDeadheadReservationRQ1/ns1:PassengerInfo/ns1:PassengerName/ns1:Surname) }</ns2:Surname>
</ns2:PersonName>
</ns2:CustomerInfo>
</ns2:TravelItineraryAddInfoRQ>
</ns2:PassengerDetailsRQ>
};
declare variable $createDeadheadReservationRQ1 as element(ns1:CreateDeadheadReservationRQ) external;
declare variable $airBookRS as element(flightCategory:GetFlightCategoryRS) external;
declare variable $CreateDeadHeadReservationAdapterSelectRS as element(ns3:RefTickettypeCollection) external;
xf:createDeadheadReservationRQ-to- PassengerDetailsRQ($createDeadheadReservationRQ1, $airBookRS, $CreateDeadHeadReservationAdapterSelectRS)
So We have to do the below changes.
for that we have created the below mentioned table in DB, using JCA adapter we have received the response and created the xml response creating business service of JCA adapter in OSB.
condition: In query we need to fetch OTHER always so query will be as follows and if we get 2 results then pick one that is not “other” like pick CPT if it returned in result of select query and if we get 1 result then it will be always “Other”.
Select *from <Table> where Code_name in (‘OTHER’, 'value received in request');
xml request and response of business service JCA adapter:
Request:
<cre:CreateDeadHeadReservationAdapterSelect_CODE_NAMEInputParameters>
<cre:CODE_NAME>CPT</cre:CODE_NAME>
</cre:CreateDeadHeadReservationAdapterSelect_CODE_NAMEInputParameters>
Response:
<cre:RefTickettypeCollection xmlns:xsi="http://www.w3.org/2001/XMLSchema- instance" xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:cre="http://xmlns.oracle.com/pcbpel/adapter/db/top/CreateDeadHeadReservati onAdapter">
<cre:RefTickettype>
<cre:codeName>CPT</cre:codeName>
<cre:codeType>Rank</cre:codeType>
<cre:priorityCode>DL3UJ</cre:priorityCode>
<cre:preferredClass>J</cre:preferredClass>
</cre:RefTickettype>
<cre:RefTickettype>
<cre:codeName>OTHER</cre:codeName>
<cre:codeType>Other</cre:codeType>
<cre:priorityCode>DL7UJ</cre:priorityCode>
<cre:preferredClass>J</cre:preferredClass>
</cre:RefTickettype></cre:RefTickettypeCollection>
So using the above response could you pls help me to create the xquery logic.
I'm not sure I understand all of your question. But, it sounds like when two RefTickettype elements are returned, you want to select the one where codeName is not OTHER?
The following query checks to see how many RefTickettype elements are in the result. If there is only one, it is returned. If there is more than one, it will return all where codeName is not OTHER.
declare namespace cre="http://xmlns.oracle.com/pcbpel/adapter/db/top/CreateDeadHeadReservationAdapter";
let $response :=
<cre:RefTickettypeCollection>
<cre:RefTickettype>
<cre:codeName>CPT</cre:codeName>
<cre:codeType>Rank</cre:codeType>
<cre:priorityCode>DL3UJ</cre:priorityCode>
<cre:preferredClass>J</cre:preferredClass>
</cre:RefTickettype>
<cre:RefTickettype>
<cre:codeName>OTHER</cre:codeName>
<cre:codeType>Other</cre:codeType>
<cre:priorityCode>DL7UJ</cre:priorityCode>
<cre:preferredClass>J</cre:preferredClass>
</cre:RefTickettype>
</cre:RefTickettypeCollection>
return
if (count($response/cre:RefTickettype) eq 1) then
$response/cre:RefTickettype
else
$response/cre:RefTickettype[cre:codeName ne "OTHER"]

wrapping child node content in xquery

I have what I hope is a really simple question, but I'm a novice at xquery and I can't make this work:
I have the following bit of xml:
<collation>1<num>12</num> 2<num>12</num> ||
I<num>8</num>-V<num>8</num>, 1 flyleaf</collation>
That I need to transform so that becomes the content of a new node, like so:
<note displayLabel="Collation: Notes">1(12) 2(12) || I(8)-V(8), 1 flyleaf<note>
I am using the following xquery code to attempt to do this:
<note displayLabel="Collation:Notes">{for $t in doc("collation.xml")//collation,
$h in distinct-values($t)
return
????
</note>
The problem is that I can either display all of the content (so without the parentheses) using data($t), or I can display just the things I want to be in parentheses (the information in the tags) using data($t/num) but I can't figure out how to display both with the items in tags wrapped in parentheses. I'm sure it's a really simple answer but I can't find it.
This is a good job for recursion:
declare function local:render(
$n as node()
) as node()?
{
typeswitch($n)
case element(num) return text{concat('(', $n, ')')}
case element(collation) return
<note displayLabel="Collation: Notes">{
for $n in $n/node()
return local:render($n)
}</note>
case element() return element { node-name($n) } {
for $n in $n/node()
return local:render($n)
}
default return $n
};
local:render(
<collation>1<num>12</num> 2<num>12</num> || I<num>8</num>-V<num>8</num>, 1 flyleaf</collation>)
=>
<note displayLabel="Collation: Notes">1(12) 2(12) || I(8)-V(8), 1 flyleaf</note>

Resources