xquery- filtering with dynamic date - xquery

I have the following code:
<Table><ColumnHeaders>
<ColumnHeader name='Title' type='xs:string' />
<ColumnHeader name='EventDate' type='xs:date' />
<ColumnHeader name='today' type='xs:date' />
<ColumnHeader name='day-week' type='xs:integer' />
<ColumnHeader name='dur-end' type='xs:integer' />
<ColumnHeader name='start-date' type='xs:date' />
<ColumnHeader name='end-date' type='xs:date' />
</ColumnHeaders>
<Data>{let $today := fn:current-date()
let $day-week := functx:day-of-week($today)
let $dur-end := 6-$day-week
let $start-date := xs:date($today)-(xs:dayTimeDuration('P1D')*$day-week)
let $end-date := xs:date($today)+(xs:dayTimeDuration('P1D')*$dur-end)
for $ancestor0 in $queryresponse//*:row
where ($ancestor0/#ows_EventDate)>=$start-date
return<Row>
<Title>{fn:data($ancestor0/#ows_Title)}</Title>
<EventDate>{fn:data($ancestor0/#ows_EventDate)}</EventDate>
<today>{fn:data($today)}</today>
<day-week>{fn:data($day-week)}</day-week>
<dur-end>{fn:data($dur-end)}</dur-end>
<start-date>{fn:data($start-date)}</start-date>
<end-date>{fn:data($end-date)}</end-date>
</Row>}
</Data></Table>
after adding the where clause in the "for statement", the xquery failed with the following error:
ZorbaDynamicException failed. Zorba engine encountered a dynamic error.
Error type: XQuery Engine error. Passed item (of type UNTYPED_ATOMIC) is not castable to passed target type (xs:date).
can someone please help me in fixing this issue?

The value resulting from $ancestor0/#ows_EventDate is not castable to a date. You can use the parse-date function contained in Zorba's datetime module (http://www.zorba.io/documentation/2.9/modules/www.zorba-xquery.com_modules_datetime.html) to convert the string into a date.
For example,
d:parse-date($ancestor0/#/#ows_EventDate/text(), "%D")
if your date is formatted as MM/DD/YY.

Related

How to do collections-not for TDE with Marklogic

I am looking to how to implement the collections-not for Marklogic TDE.
The equivalent one for the CTS query is
cts:not-query(cts:collection-query("archived"))
According to TDE documentation, it only supports AND, OR collections. I am looking for NOT collections with TDE schema.
EDIT: I changed the sample from: '.. = "include"..' to '... != "exclude"...' They both work. However, for the context of the question, not-equal makes more sense in an example.
As odd as it seems, the feature that you are asking for is not available. However, there is a way to make use of the context that can help you. First of all, it is still good to set a collection or collection scope so that we minimize the sample set to analyze the context path.
The approach is to use xPath and xQuery on the context as a filter.
Below is a working sample for Query Console. Please not the ';' in the code as it is a multi-statement sample.
xquery version "1.0-ml";
let $_ := xdmp:document-insert("/llamas/Jalliue.xml", <llama><name>Jalliue</name></llama>, map:new()=>map:with("collections", ("llama", "include")))
let $_ := xdmp:document-insert("/llamas/Sven.xml", <llama><name>Sven</name></llama>, map:new()=>map:with("collections", ("llama", "exclude")))
return ();
let $docs := (fn:doc("/llamas/Jalliue.xml"), fn:doc("/llamas/Sven.xml"))
let $template :=
<template xmlns="http://marklogic.com/xdmp/tde">
<description>llama list</description>
<context>/llama[xdmp:node-collections(.) != "exclude"]</context>
<rows>
<row>
<schema-name>llama</schema-name>
<view-name>list</view-name>
<columns>
<column>
<name>name</name>
<scalar-type>string</scalar-type>
<val>name</val>
</column>
</columns>
</row>
</rows>
</template>
return tde:node-data-extract($docs, $template)
The result shows that both documents were considered, but only the one with the collection "include" is parsed.
{
"/llamas/Jalliue.xml": [
{
"row": {
"schema": "llama",
"view": "list",
"data": {
"rownum": "1",
"name": "Jalliue"
}
}
}
],
"/llamas/Sven.xml": []
}

Exist-db Add node with XQUERY

I have a listPers.xml (TEI List containing persons, obviously ) . I want to write a function to update the listPers.xml
My function looks like this:
declare function app:addPerson($node as node(), $model as map(*)) {
let $person := "<person xml:id=""><persName><forename>Albert</forename><surname>Test</surname></persName></person>"
let $list := doc(concat($config:app-root, '/resources/listPers_test.xml'))
return
update insert $person into $list//tei:listPerson
};
And the listPerson.xml
looks more or less like a typical list with person-entries
I have a tei:header (here omitted) followed by
<text>
<body>
<listPerson xml:id="person">
<person xml:id="abbadie_jacques">
<persName ref="http://d-nb.info/gnd/100002307">
<forename>Jacques</forename>
<surname>Abbadie</surname>
</persName>
<note>Prediger der französisch-reformierten Gemeinde in <rs type="place" ref="#berlin">Berlin</rs>
</note>
</person>
</body>
</text>
</TEI>
(sorry for ruining indentions, it's just an excerpt )
I do not get an error, which means that my app:addPerson should be fine, right?
I want the listPers_test to look like this:
<text>
<body>
<listPerson xml:id="person">
<person xml:id="abbadie_jacques">
<persName ref="http://d-nb.info/gnd/100002307">
<forename>Jacques</forename>
<surname>Abbadie</surname>
</persName>
<note>Prediger der französisch-reformierten Gemeinde in <rs type="place" ref="#berlin">Berlin</rs>
</note>
</person>
<!-- here comes the output that I wish to have :-) -->
<person xml:id=""><persName><forename>Albert</forename><surname>Test</surname></persName></person>
</body>
</text>
</TEI>
In the long run, I aim for an html-form that allows users to input names etc., where ids are generated using sth like
to-lowercase(concat($surname, "_", $forename));
But I will not get into my questions regarding forms and xquery, as I have barely done a quick Google-trip regarding html forms and xquery!
Can anyone hint me at why I do not get the listPers_test.xml file updated with the second value? :-)
All the best and thanks in advance to everyone,
K
Alright, I have a solution for anyone interested in it:
My first snippet $person:= ... contains a STRING, not an element.Changing the line
let $person := "<person xml:id=""><persName><forename>Albert</forename><surname>Test</surname></persName></person>"
to this one actually solves the issue:
let $person := <tei:person xml:id=""><persName><forename>Albert</forename><surname>Test</surname></persName></tei:person>

XQuery Replace Value With Conditional Failing

i am in the middle of creating xquery replace-value of node action in XQuery.
But seems this code is not working therefore the IF-ELSE statement is always going to else.
This is my code:
declare function local:replacing($contextData as element())
as element()*
{
copy $pipeline := $contextData/Handler/Data/*
modify(
if(not(empty(data($pipeline/Payload/sample/transactionType)))) then
replace value of node $pipeline/Payload/sample/transactionType with 'XXX' else (),
if(not(empty(data($pipeline/Payload/sample/revision)))) then
replace value of node $pipeline/Payload/sample/revision with 'XXX' else ()
)
return $pipeline
};
I try against this sample XML but the result is always not XXX when the field revision is having value. (this always goes to else statement)
let $result :=
<root>
<Handler>
<Data>
<root>
<Payload>
<sample>
<transactionType></transactionType>
<revision>123</revision>
<board>1</board>
<mission>1</mission>
<method>Manual</method>
<listOfBoard>
<board>
<type>small</type>
<amount>5054</amount>
<token>300</token>
</board>
</listOfBoard>
<pricing>300</pricing>
<playing>Wed</playing>
</sample>
</Payload>
</root>
</Data>
</Handler>
</root>
Current Result:
<root>
<Payload>
<sample>
<transactionType/>
<revision>123</revision>
<board>1</board>
<mission>1</mission>
<method>Manual</method>
<listOfBoard>
<board>
<type>small</type>
<amount>5054</amount>
<token>300</token>
</board>
</listOfBoard>
<pricing>300</pricing>
<playing>Wed</playing>
</sample>
</Payload>
</root>
Expected Result
<root>
<Payload>
<sample>
<transactionType/>
<revision>XXX</revision>
<board>1</board>
<mission>1</mission>
<method>Manual</method>
<listOfBoard>
<board>
<type>small</type>
<amount>5054</amount>
<token>300</token>
</board>
</listOfBoard>
<pricing>300</pricing>
<playing>Wed</playing>
</sample>
</Payload>
</root>
Any ideas for this?
Update
As recommended by Har below, i change the code into:
if(not(empty(data($pipeline/Payload/sample/transactionType)))) then
replace value of node $pipeline/Payload/sample/transactionType with 'XXX'
else (
if(not(empty(data($pipeline/Payload/sample/revision)))) then
replace value of node $pipeline/Payload/sample/revision with 'XXX' else ()
)
But seems the result is the same. It still goes to else () statement.
Any ideas?
Thank you before.
The problem was, empty() checks for empty sequence, so sequence containing one empty string is considered true by empty(). You can just pass data() result to if since empty has Effective Boolean Value of false :
if(data($pipeline/Payload/sample/transactionType)) then
replace value of node $pipeline/Payload/sample/transactionType with 'XXX' else (),
if(data($pipeline/Payload/sample/revision)) then
replace value of node $pipeline/Payload/sample/revision with 'XXX' else ()

Struct being populated with duplicate data over and over

Consider the following code:
<cfset result.enrollments = {} />
<cfset result.enrollments = getCorrectionList(SESSION.id,SESSION.term) />
<cfdump var="#result#" /><Cfabort/>
<cffunction name="getCorrectionList">
<cfargument name="id" required="true" type="string" />
<cfargument name="term" required="true" type="numeric" default="#getCurrentSemester().code#" />
<cfset result = {} />
<cfset result.status = 500 />
<cfset result.message = 'Unknown Error' />
<cfhttp url="THERE IS A REAL URL HERE" />
<cfif cfhttp.statusCode EQ '200 OK'>
<cfset courses = deserializeJson(cfhttp.fileContent,false) />
<cfif courses.recordCount EQ 0>
<cfset result.message = 'You are not currently enrolled in any courses for #ARGUMENTS.term#' />
<cfdump var="#result#" />
<cfreturn result />
</cfif>
<!--- MORE STUFF --->
Now when this runs I get an single struct output with two keys message and status. This is from the dump inside of the getCorrectionList function.
I then get a second struct output with the keys enrollments, message, and status. Inside the enrollments key is another struct with enrollments, message, and status. Inside that enrollments key is another struct with the same keys and so on 50 times with the last struct being empty.
Seems like some recursive actions is going on but where/how?
I have no idea what is going on. As you can see from my code there are no loops. I know the URL resolves correctly and it returns a query and has a recordcount. I can see the data dump at the right spots. But how can the #result# in the function show a single struct but the #result# outside the function show a 50 deep struct repeating itself. It doesn't make any sense.
I dunno why neither Leigh or Scott actually made their comments answers, but they're both right.
You have this reference to result outside your function:
<cfset result.enrollments = getCorrectionList(SESSION.id,SESSION.term) />
And at the end of your function you do this:
<cfreturn result />
Which in effect means you're doing this:
<cfset result.enrollments = result />
Meaning result.enrollments is a reference back to its own parent result.
And <cfdump> is duly displaying the circular reference.
As they both said, you need to localise your variables inside a function, either by varing them:
<cfset var result = {} />
Or explicitly putting them in the local scope:
<cfset local.result = {} />
That will make the function's result be a discrete variable, not simply another reference to the calling code' result variable.
You should always localise your function variables, unless you specifically mean to be referencing a calling-code variable, in which event it makes you code clearer if you explicitly scope it to make it obvious what you mean, eg:
<cfset variables.result = {} />
But this is not what you are meaning to do here. Localise your function's variables.

Read multi level XML in and write back to single data base table

I'm a nube with asp.net. This is what I'm trying to achieve. I want to write the following XML data into a single table in a sql server database.
- <RaceDay RaceDayDate="2012-05-16T00:00:00" Year="2012" Month="5" Day="16" DayOfTheWeek="Wednesday" MonthLong="May" IsCurrentDay="1" IsPresaleMeeting="0" ServerTime="2012-05-16T16:47:30.033">
- <Race RaceNo="7" RaceTime="2012-05-16T16:36:00" CloseTime="2012-05-16T16:40:08.107" RaceName="F&M BM 70 HANDICAP" Distance="1200" SubFav="1" RaceDisplayStatus="PAYING" WeatherChanged="N" WeatherCond="1" WeatherDesc="Fine" TrackChanged="N" TrackCond="1" TrackDesc="Good" TrackRating="3" TrackRatingChanged="N">
- <TipsterTip TipsterId="0" Tips="1">
<Tipster TipsterName="LATE MAIL" />
</TipsterTip>
- <TipsterTip TipsterId="1" Tips="8-5-3-7">
<Tipster TipsterName="RADIO TAB" />
</TipsterTip>
- <TipsterTip TipsterId="2" Tips="1-10-9-2">
<Tipster TipsterName="KEVIN CASEY" />
</TipsterTip>
- <Pool PoolType="EX" Available="Y" Abandoned="N" PoolDisplayStatus="PAYING" PoolTotal="3734.00" JPotInGross="0.00" JPotOutGross="0.00" LastCalcTime="2012-05-16T16:36:57" CalcTime="2012-05-16T16:41:31" StatDiv="0">
- <Dividend DivId="62406790" DivAmount="80.8000">
<DivResult LegNo="1" RunnerNo="7" />
<DivResult LegNo="2" RunnerNo="5" />
</Dividend>
</Pool>
- <Pool PoolType="F4" Available="Y" Abandoned="N" PoolDisplayStatus="PAYING" PoolTotal="3492.00" JPotInGross="0.00" JPotOutGross="1397.16" LastCalcTime="2012-05-16T16:36:57" CalcTime="2012-05-16T16:41:31" StatDiv="0">
- <Dividend DivId="62406797" DivAmount="10828.0000">
<DivResult LegNo="1" RunnerNo="7" />
<DivResult LegNo="2" RunnerNo="5" />
<DivResult LegNo="3" RunnerNo="13" />
<DivResult LegNo="4" RunnerNo="1" />
</Dividend>
</Pool>
- <Pool PoolType="QN" Available="Y" Abandoned="N" PoolDisplayStatus="PAYING" PoolTotal="7029.00" JPotInGross="0.00" JPotOutGross="0.00" LastCalcTime="2012-05-16T16:36:57" CalcTime="2012-05-16T16:41:31" StatDiv="0">
- <Dividend DivId="62406785" DivAmount="68.5000">
<DivResult LegNo="1" RunnerNo="5" />
<DivResult LegNo="2" RunnerNo="7" />
</Dividend>
</Pool>
</Race>
</Meeting>
</RaceDay>
Can someone please show me how to read in my xml file and flatten out the data and insert it into a suitable table in the sql database.
Thanks in advance.
Search in web, there are lots of article described about your requirement. Try this one:
Best way to load XML files to SQL Server using C#
And
Importing Large Xml Files to SQL Server Using SqlBulkCopy
First you have to parse the XML and store that into custom C# object or you can directly pass the XML to your stored procedure and do the codding there for saving it into DB.
Passing the xml to stored procedure and manipulating it there is bit difficult so what I suggest is to parse it in C# and then get a custom object. Once you get it you can do whatever you want to.
Here is my article that explains exactly what you need.
Read XML file in ASP.NET(C#)
Below is the sample code that parse a XML file and generate a custom C# object from it.
public CatSubCatList GenerateCategoryListFromProductFeedXML()
{
string path = System.Web.HttpContext.Current.Server.MapPath(_xmlFilePath);
XDocument xDoc = XDocument.Load(path);
XElement xElement = XElement.Parse(xDoc.ToString());
List<Category> lstCategory = xElement.Elements("Product").Select(d => new Category
{
Code = Convert.ToString(d.Element("CategoryCode").Value),
CategoryPath = d.Element("CategoryPath").Value,
Name = GetCateOrSubCategory(d.Element("CategoryPath").Value, 0), // Category
SubCategoryName = GetCateOrSubCategory(d.Element("CategoryPath").Value, 1) // Sub Category
}).GroupBy(x => new { x.Code, x.SubCategoryName }).Select(x => x.First()).ToList();
CatSubCatList catSubCatList = GetFinalCategoryListFromXML(lstCategory);
return catSubCatList;
}

Resources