XQuery tumbling windows: how to match first occurrence of a grouping key? - xquery

I have a CSV file of an SQL dump, and I am working with it in BaseX 8.4. The CSV headers contain a flattened representation of the SQL table structure.
CSV with header and first row:
country_id,country_code,country_name,publisher_id,publisher_name,country id,year_began,year_ended,series_id,series_name,sort_name,publisher_id
2,us,United States,78,Harvard University Press,2,1950,NULL,15,A New Series,New Series,78
The BaseX CSV parser produces the following XML representation:
<csv>
<record>
<country_id>2</country_id>
<country_code>us</country_code>
<country_name>United States</country_name>
<publisher_id>78</publisher_id>
<publisher_name>Harvard University Press</publisher_name>
<country_id>2</country_id>
<year_began>1950</year_began>
<year_ended>NULL</year_ended>
<series_id>15</series_id>
<series_name>A New Series</series_name>
<sort_name>New Series</sort_name>
<publisher_id>78</publisher_id>
</record>
</csv>
Regarding the original data, I know that the start of a table begins with its unique ID, but those ID names will also appear repeated in other tables as foreign keys.
I would like to create windows/groups that reconstruct the original table structure by matching the first occurrence of a table's unique ID (while ignoring each subsequent occurrence). What I have so far doesn't work because it matches every occurrence of the ID, not just the first one:
<tables>{
for tumbling window $w in /csv/record/*
start $s at $p when name($s) = ("country_id",
"publisher_id",
"series_id",
"issue_id",
"id_activity_fact",
"id_person_dim",
"id_location_dim",
"id_phys_loc_dim",
"id_letter_dim")
return <table id_name="{name($s)}">{$w}</table>
}</tables>
Output:
<tables>
<table id_name="country_id">
<country_id>2</country_id>
<country_code>us</country_code>
<country_name>United States</country_name>
</table>
<table id_name="publisher_id">
<publisher_id>78</publisher_id>
<publisher_name>Harvard University Press</publisher_name>
</table>
<table id_name="country_id">
<country_id>2</country_id>
<year_began>1950</year_began>
<year_ended>NULL</year_ended>
</table>
<table id_name="series_id">
<series_id>15</series_id>
<series_name>A New Series</series_name>
<sort_name>New Series</sort_name>
</table>
<table id_name="publisher_id">
<publisher_id>78</publisher_id>
</table>
</tables>
Desired output:
<tables>
<table id_name="country_id">
<country_id>2</country_id>
<country_code>us</country_code>
<country_name>United States</country_name>
</table>
<table id_name="publisher_id">
<publisher_id>78</publisher_id>
<publisher_name>Harvard University Press</publisher_name>
<country_id>2</country_id>
<year_began>1950</year_began>
<year_ended>NULL</year_ended>
</table>
<table id_name="series_id">
<series_id>15</series_id>
<series_name>A New Series</series_name>
<sort_name>New Series</sort_name>
<publisher_id>78</publisher_id>
</table>
</tables>

I think you may need to use your windowing solution for the initial splitting into segments, and then use "group by" on the result to merge segments having the same key.

After working on this for quite some time, I gave up and decided simply to mark the subsequent occurrences of the ID names with an underscore, like so:
<csv>
<record>
<country_id>2</country_id>
<country_code>us</country_code>
<country_name>United States</country_name>
<publisher_id>78</publisher_id>
<publisher_name>Harvard University Press</publisher_name>
<_country_id>2</_country_id>
<year_began>1950</year_began>
<year_ended>NULL</year_ended>
<series_id>15</series_id>
<series_name>A New Series</series_name>
<sort_name>New Series</sort_name>
<_publisher_id>78</_publisher_id>
</record>
</csv>
In this way, the window expression works as desired; then, I simply strip off the underscores to return the element names to their original form:
<tables>{
for tumbling window $w in /csv/record/*
start $s when $s/name() = ("country_id",
"publisher_id",
"series_id",
"issue_id",
"id_activity_fact",
"id_person_dim",
"id_location_dim",
"id_phys_loc_dim",
"id_letter_dim")
return
<table id_name="{$s/name()}">{
for $e in $w
return
if (starts-with($e/name(), "_")) then
element {$e/substring-after(name(), "_")} { $e/string() }
else $e
}</table>
}</tables>
Final result:
<tables>
<table id_name="country_id">
<country_id>2</country_id>
<country_code>us</country_code>
<country_name>United States</country_name>
</table>
<table id_name="publisher_id">
<publisher_id>78</publisher_id>
<publisher_name>Harvard University Press</publisher_name>
<country_id>2</country_id>
<year_began>1950</year_began>
<year_ended>NULL</year_ended>
</table>
<table id_name="series_id">
<series_id>15</series_id>
<series_name>A New Series</series_name>
<sort_name>New Series</sort_name>
<publisher_id>78</publisher_id>
</table>
</tables>

Related

How to embed file content into body of the email using mail command?

I have requirement,where i need to send file content as mail body.can we dot through unix scripting.
Thanks in Advance
With the data create a html file. And then send that file in email as content.
use an expression to create your file data like this -
v_data= ' <tr>
<td>'||company ||'</td>
<td>'|| contact_person|| '</td>
<td>'|| country ||'</td>
</tr>'
Use an aggregator to concat all these data into one single row. group by none.
Then use another expression transformation.
create a ports like this -
v_head ='
<head></head>
<body>
<b>pls find below data.</b>
<table>
<tr>
<th>Company</th>
<th>Contact</th>
<th>Country</th>
</tr>'
v_body = Aggregated_v_data
v_tail='</table></body>'
v_output = v_head||v_body ||v_tail
Then use this output and connect to a flat file target.
Then send this flat file sing mailx command/any mail client.
Output should look like this.
html file should looks like this
<head></head>
<body>
pls find below data.
<br> </br>
<table>
<tr>
<th>Company</th>
<th>Contact</th>
<th>Country</th>
</tr>
<tr>
<td>Alfreds </td>
<td>Maria </td>
<td>Germany</td>
</tr>
</table>
</body>

How to Iterate List of JSONObject in Thymeleaf using th:each

Here is that list of JSONObject which is coming from Spring MVC Controller.
List<JSONObject> jsonDataList =
[{"key1":"value1","key2":"value2","key3":"value3","key4":"value4"}, {"key1":"value1","key2":"value2","key3":"value3","key4":"value4"}]
How to Iterate List of JSONObject in Thymeleaf using th:each?
Code IN HTML FILE below:=>
<tr th:each="data: ${jsonDataList}">
<td align="center"><span th:text="${data.key1}"></span></td> // getting exception here
</tr>
Getting Exception as :
Caused by: org.attoparser.ParseException: Exception evaluating SpringEL expression: "data.key1"
Here is one approach, but it makes some assumptions:
a) Each JSON object has the same number of entries (otherwise you could have a ragged table, containing different numbers of cells in each row).
b) Each JSON object has the same keys in the same order (if you want the table to have consistent column headings).
Also, the sample JSON in the question assumes all values are strings (value1 and so on). If you have different types of objects in your JSON values, then you will need to ensure they have the required string representations (e.g. using toString()).
The approach:
<table>
<tr>
<th:block th:each="heading : ${jsonDataList.get(0).names()}">
<th th:text="${heading}"></th>
</th:block>
</tr>
<tr th:each="item : ${jsonDataList}">
<th:block th:each="name : ${item.names()}">
<td th:text="${item.get(name)}"></td>
</th:block>
</tr>
</table>
The first <tr> section handles reading the JSON object keys from the first object in the list:
${jsonDataList.get(0).names()}
The final <tr> section is similar, but uses the keys to look up their related values:
${item.get(name)}
The resulting HTML gives you a simple table:
<table>
<tr>
<th>key1</th>
<th>key2</th>
<th>key3</th>
<th>key4</th>
</tr>
<tr>
<td>value1</td>
<td>value2</td>
<td>value3</td>
<td>value4</td>
</tr>
<tr>
<td>value1</td>
<td>value2</td>
<td>value3</td>
<td>value4</td>
</tr>
</table>
References:
The th:block tag is documented here.
The methods available to be used for JSONObject are documented here.
how about this?
<tr th:each="data: ${jsonDataList}">
<td align="center"><span th:text="[[${data.key1}]]"></span></td>
</tr>

When iterating with {{#each}} how to not include the entry in Meteor

The person I'm designing this app for requested that she be able to make a email list of people with birthdays within the next 7 days. One of the fields in the collection is Bdate in the format 'YYYY-MM-DD'. I decided to make a registerHelper with a simple algorithm that determines if the birthdate is one that fit the request:
Template.registerHelper('calculateBirthday', function(bdate) {
var birthDate = new Date(bdate);
var current = new Date();
var diff = current - birthDate; // Difference in milliseconds
var sevenDayDiff = Math.ceil(diff/31557600000) - (diff/31557600000);
if (sevenDayDiff <= 0.01995183087435)
return date;
else
return false;
});
The template would have a table that lists the birthdates that are the ones to get for the email list:
<table class="bordered">
<thead>
<tr>
<th>Name</th>
<th>Birthday</th>
</tr>
</thead>
<tbody>
{{#each QueryBirthday}}
<tr>
<tr>{{FullName}}</tr>
<td>{{calculateBirthday Bdate}}</td>
</tr>
{{/each}}
</tbody>
</table>
The problem with this is that it prints all the names with mostly blank birthdates. The algorithm works fine, but how to tell Meteor to only include those names and birthdates that 'should' be on the list?
The quickest way to hide unwanted items is
<table class="bordered">
<thead>
<tr>
<th>Name</th>
<th>Birthday</th>
</tr>
</thead>
<tbody>
{{#each QueryBirthday}}
{{#if calculateBirthday Bdate}}
<tr>
<td>{{FullName}}</td>
<td>{{calculateBirthday Bdate}}</td>
</tr>
{{/if}}
{{/each}}
</tbody>
</table>
I don't know how your application works, but like other people who commented on your question, I would filter and send only the required results from server to client.

How to import and save data from csv in web2py database table?

I used SQlite database.
I wrote code like this
Module:
db.py
db = DAL('sqlite://storage.sqlite')
db.define_table('data3')
db.data3.import_from_csv_file(open('mypath/test.csv'),'r')
Controller:
def website_list():
return dict(websites = db().select(db.data4.ALL))
View:
{{extend 'layout.html'}}
<h2>List Of Websites</h2>
<table class="flakes-table" style="width:100% ;">
<thead>
<tr>
<td class="id" >ID</a></td>
<td class="link" >Link</td>
</tr>
</thead>
{{for web in websites:}}
<tbody class="list">
<tr>
<td >{{=web.id}}</td>
<td >{{=web.Link}</td>
</tr>{{pass}}
</tbody>
</table>
But it is showing error as
"type 'exceptions.AttributeError'"
Also error has this line
Function argument list
(self=, key='data3')
I think some thing is wrong in reading csv file. My csv file has following data
"Link_Title","Link"
"Apple's Ad Blockers Rile Publishers","somelink"
"Uber Valued at More Than $50 Billion","somelink"
"England to Roll Out Tailored Billboards","somelink"
Can anyone help in this..?

XQuery if statement

I have problem with XQuery. I've spend on this proble a lot of time, and I can't make it work :( Here is my XML book node:
<book id="bk101">
<author>Gambardella, Matthew</author>
<title>XML Developer's Guide</title>
<genre>Computer</genre>
<price>44.95</price>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at creating applications
with XML.</description>
</book>
That's what i want to achive:
<table>
<tr>
<td>
<b>XML Developer's Guide</b>
</td>
<td class="author">Gambardella, Matthew</td>
<td class="genre">Computer</td>
<td class="price">44.95</td>
<td class="priceVat">55.29</td>
<td class="publish_date">2000-10-01</td>
<td class="description">An in-depth look at creating applications
with XML.</td>
</tr>
</table>
And here is my XQuery code:
for $book in doc("/home/kuba/mgr/pliki/books.xml")//book
order by number($book/price) descending
return
<tr>
<td><b>{ string($book/title) }</b></td>
{
for $value in $book/*
return if($value != $book/title and name($value) != 'price') then
<td class="{name($value)}">{$value/text()}</td>
else
if(name($value) = 'price') then
<td class="{name($value)}">{$value/text()}</td>
<td class="{name($value)}Vat">{$value/text()*1.23}</td>
else ()
}
</tr>
The problem is in this line:
<td class="{name($value)}Vat">{$value/text()*1.23}</td>
Here is my error message:
Engine name: Saxon-PE XQuery 9.5.0.2
Severity: fatal
Description: XPST0003: expected "else", found name "class"
Start location: 17:0
URL: http://www.w3.org/TR/xpath20/#ERRXPST0003
How i can make it? Is possible to format number in XQuery 1.0, i read that th is not possible but I want to make sure :)
Following your then clause you return a sequence of <td> elements, but they need to be wrapped in parentheses and separated by a comma:
if(name($value) = 'price') then
(<td class="{name($value)}">{$value/text()}</td>,
<td class="{name($value)}Vat">{$value/text()*1.23}</td>)
else ()

Resources