Used HANA XS to create a HANA DB and expose it via OData - unable to POST using Postman - hana-xs

I used HANA XS on SAP Cloud Platform Neo to create a HANA DB and expose it via OData - unable to POST using Postman. I get a 400 - Bad Request - "Syntax error at position 0."
Here is the .xsodata file contents:
service{
"com.******.jereclass::JeReclassHistory";
}
Here is the .xsaccess file contents:
{
"exposed": true,
"authentication": [{
"method": "Form"
}],
"mime_mapping": [{
"extension": "jpg",
"mimetype": "image/jpeg"
}],
"force_ssl": false,
"enable_etags": true,
"prevent_xsrf": false,
"anonymous_connection": null,
"cors": [{
"enabled": true,
"allowMethods":["GET","POST"]
}],
"cache_control": "no-cache, no-store",
"default_file": "index.html"
}
Here is the .hdbschema file contents:
schema_name = "JE_Reclass";
Here is the .hdbtable file contents:
table.schemaName = "JE_Reclass";
table.tableType = COLUMNSTORE;
table.columns = [
{ name = "Department"; sqlType = VARCHAR; nullable = false; length = 20; },
{ name = "MapName"; sqlType = VARCHAR; nullable = false; length = 30; },
{ name = "FiscalYear"; sqlType = VARCHAR; nullable = false; length = 4; },
{ name = "Period"; sqlType = VARCHAR; nullable = false; length = 3; },
{ name = "RunID"; sqlType = VARCHAR; nullable = false; length = 30; },
{ name = "PostingDate"; sqlType = DATE; nullable = false; },
{ name = "FromDate"; sqlType = DATE; nullable = false; },
{ name = "FromTime"; sqlType = TIME; nullable = false; },
{ name = "ToDate"; sqlType = DATE; nullable = false; },
{ name = "ToTime"; sqlType = TIME; nullable = false; },
{ name = "CreateBy"; sqlType = VARCHAR; nullable = false; length = 12; },
{ name = "CreateDate"; sqlType = DATE; nullable = false; },
{ name = "CreateTime"; sqlType = TIME; nullable = false; }
];
table.primaryKey.pkcolumns = ["Department", "MapName", "FiscalYear", "Period", "RunID"];
****Postman:****
POST /com/*******/jereclass/JeReclassHistorySvc.xsodata/JeReclassHistory HTTP/1.1
Host: jereclass******.us3.hana.ondemand.com
Content-Type: application/json
Authorization: Basic **************
User-Agent: PostmanRuntime/7.18.0
Accept: */*
Cache-Control: no-cache
Postman-Token: ***********************
Host: jereclass******.us3.hana.ondemand.com
Accept-Encoding: gzip, deflate
Content-Length: 456
Cookie: *****************************
Connection: keep-alive
cache-control: no-cache
{
"Department": "Payroll",
"MapName": "TEST JE RECLASS",
"FiscalYear": "2013",
"Period": "01",
"RunID": "20130112134231-SCURRY",
"PostingDate": "2013-01-12T00:00:00.0000000",
"FromDate": "2013-01-01T00:00:00.0000000",
"FromTime": "PT1H10M54S",
"ToDate": "2013-01-12T00:00:00.0000000",
"ToTime": "PT13H42M30S",
"CreateBy": "SCURRY",
"CreateDate": "2013-01-12T00:00:00.0000000",
"CreateTime": "PT14H5M7S"
}

Using (for example) "PostingDate": "/Date(1405699200)/", where "1405699200" is the epoch date worked.

Related

Highcharts - Lazy loading combined with SQL queries

Based on the Lazy Loading Example I wanted to create the similar function for my Highcharts.StockChart. But with the aid of Ajax.
Some words about the database structure:
Tables contains the values of 1 month
Column 'tijd' contains a timestamp
Values are posted every minute to the database, resolution = 1 minute
Please focus on why the zoom function isn't updating the chart. This drives me #!#
For the first time generation of the chart I use this code, which works fine
JAVASCRIPT:
function generateChart(param, options)
{
// EERST DE GESELECTEERDE GEGEVENS GAAN OPVRAGEN
data = param.join();
console.log(data);
t_min = new Date(2015, 0, 1, 0, 0, 0, 0);
t_max = Date.now();
console.log(t_min, t_max);
console.log((t_max - t_min) / 1000);
$.ajax({
url: url,
data: { "data": data, "db": klantnummer, "t_min": t_min, "t_max": t_max },
type: "POST",
async: false,
cache: false,
success:
function (gegevens)
{
// GEGEVENS OPSLAAN IN DE OPTIE.SERIES
console.log('Gegevens:');
console.log(gegevens); //werkt!
options.series = gegevens;
}
});
//EFFECTIEF AANMAKEN VAN DE GRAFIEK
chart = new Highcharts.StockChart(options);
}
PHP:
// READ THE COLUMN NAMES
$data_in = $_POST['data'];
// DATA_IN to array
$name = explode(",", $data_in);
// count the amount of columns
$c_name = count($name);
$name_sql = implode(", ", $name);
//Connection with database
$klantnummer = $_POST['db'];
require 'connectie.php';
//ZOOM: min and max values are converterd to PHP UNIX EPOCH time
$t_min = ($_POST['t_min'])/1000;
$t_max = ($_POST['t_max'])/1000;
$range = $t_max - $t_min;
//Doesn't work, don't need it to load the chart
//$startTime = $t_min->format('m-d-Y H:i:s');
//$stopTime = $t_max->format('m-d-Y H:i:s');
//we only ask a query if there are enough columns
if ($c_name > 0) {
//Ask the names of the tables from the database
$sql = "SELECT TABLE_NAME FROM information_schema.tables WHERE TABLE_NAME LIKE 'T%' ORDER BY TABLE_NAME DESC";
$tableName = sqlsrv_query($conn, $sql);
if ( $tableName === false ) {
die(print_r(sqlsrv_errors(), true));
};
$t = array();
while ($row = sqlsrv_fetch_array($tableName)) {
array_push($t, $row['TABLE_NAME']);
};
// So we know the range, which filter should we apply?
if ($range < 14 * 24 *3600) { //2 weeks
$tijdspanne = 2; // load 2 tables
$filter = 1; // show every minute
} elseif ($range < 28 * 24 *3600) { //4 weeks
$tijdspanne = 2; // load 2 tables
$filter = 5; // show every 5 minutes
} elseif ($range < 3 * 28 * 24 *3600) { //3 months
$tijdspanne = 4; // load 4 months
$filter = 15; // show every 15 minutes
} else {
$tijdspanne = count($t); // load every table
$filter = 60; // show every 60 minutes
}
//Namen zijn gekend, nu in query steken om daarna op te vragen
$sql = "select tijd,".$name_sql." FROM ".$t[0]." where datepart(mi,tijd) % ".$filter." = 0";// AND tijd BETWEEN ".$startTime." AND ".$stopTime;
for ($x = 1; $x < count($t) and $x < $tijdspanne ; ++$x ) {
$sql .= " union all select tijd,".$name_sql." FROM ".$t[$x]." where datepart(mi,tijd) % ".$filter." = 0";// AND tijd BETWEEN ".$startTime." AND ".$stopTime;
};
$sql .= " ORDER BY tijd";
//DATA from MS SQL server, save to arrays
$stmt = sqlsrv_query($conn, $sql);
if ( $stmt === false ) {
die(print_r(sqlsrv_errors(), true));
}
while ($row = sqlsrv_fetch_array($stmt)) {
$tijd_U = $row["0"]->format("U");
$tijd = ($tijd_U) * 1000; //date format to javascript
for ($i = 0; $i < $c_name; ++$i) {
$j = $i +1;
$data[$i][]= array($tijd, $row[$j]);
}
}
// prepare JSON format
$data_output = array();
for ($i = 0; $i < $c_name; ++$i) {
$data_output[$i] = array('name' => $name[$i], 'data' => $data[$i]);
}
}
// admit we use JSON
header('Content-Type: application/json');
// send the data to the user
echo json_encode($data_output, JSON_NUMERIC_CHECK);
So this code works, but when the user zooms in. The graph doens't update.
JAVASCRIPT:
function afterSetExtremes(e)
{
console.log(Math.round(e.min));
chart.showLoading('Loading data from server...');
$.ajax({
url: url,
data: { "data": data, "db": klantnummer, "t_min": Math.round(e.min), "t_max": Math.round(e.max) },
type: "POST",
async: false,
cache: false,
success:
function (gegevens)
{
// GEGEVENS OPSLAAN IN DE OPTIE.SERIES
console.log('Gegevens:');
console.log(gegevens); //werkt!
options.series = gegevens;
}
});
chart.hideLoading();
}
With this set of options:
function generateChartOptions(div, ymax, ymin)
{
var options = {
navigator: {
adaptToUpdatedData: false,
series: {
includeInCSVExport: false
}
},
chart: {
renderTo: div,
type: 'line',
zoomType: 'x'
},
rangeSelector: {
buttons: [{
type: 'day',
count: 1,
text: '1d'
}, {
type: 'week',
count: 1,
text: '1w'
}, {
type: 'week',
count: 2,
text: '2w'
}, {
type: 'all',
text: 'All'
}],
selected: 4,
inputBoxWidth: 150,
inputDateFormat: '%d-%m-%Y %H:%M',
inputEditDateFormat: '%d-%m-%Y %H:%M'
},
legend: {
enabled: true
},
xAxis: {
type: 'datetime',
events: {
afterSetExtremes: afterSetExtremes,
setExtremes: function (e)
{
$('#testveld').html('<b>Set extremes:</b> e.min: ' + Highcharts.dateFormat(null, e.min) +
' | e.max: ' + Highcharts.dateFormat(null, e.max) + ' | e.trigger: ' + e.trigger);
}
},
minRange: 60 * 1000 //1 minuut
},
yAxis: {
opposite: false,
max: ymax,
min: ymin
},
plotOptions: {
line: {
tooltip: {
valueDecimals: 1
}
}
},
scrollbar: {
liveRedraw: false
},
series: [{}]
};
return options;
}

Knockout JSON null when received from service

I have an object which I wish to send to a WCF service, but object dosent get properly converted to be used on the other side as the ActiveFarmer and Evidence are always null. I have tested it with a hardcoded JSON and it works but the knockout object is not coming through properly, the object is as follows
self.afi = {
ActiveFarmer: {
ActiveFarmerID: ko.observable(),
BusinessID: ko.observable(),
Year: ko.observable(),
StatusID: ko.observable(),
Status:ko.observable(),
DecisionDate: ko.observable(),
UserID: ko.observable(""),
DateModified: ko.observable(),
// RowStatus: ko.observable(""),
},
// TODO - RH we used to add a default empty new line here...
ActiveFarmerEvidence: ko.observableArray(),
NotepadIdentifiers: ko.observableArray()
};
I am calling a wcf service
public int UpdateFarmerInfo(ActiveFarmerInfo afi)
{
return ActiveFarmerInfoManager.UpdateFarmerInfo(afi);
}
My ajax call is as follows
var afi = vm.afi;
$.ajax({
type: "POST",
contentType: "application/json",
url: rootcap + "ActiveFarmerService.svc/rest/UpdateFarmer",
data: JSON.stringify(afi),
dataType: "json",
async: true,
cache: false,
success: function (data, textStatus) {
self.populateFarmerDetails(data);
},
error: function (data, status, error) { }
});
The entire view model is
function ActiveFarmerModel() {
var self = this;
self.businessId = ko.observable();
self.individualId = ko.observable();
self.currentAppId = ko.observable();
self.userId = ko.observable();
self.evidenceCategories = ko.observableArray();
self.activeFarmerEvidenceCategories = ko.observableArray();
self.businessStatus = ko.observableArray([{ "intStatusID": "2", "vcrStatus": "Provisionally Non-Oct" }, { "intStatusID": "1", "vcrStatus": "Active" }, { "intStatusID": "3", "vcrStatus": "Negative List" }, { "intStatusID": "4", "vcrStatus": "Active (Non Verified)" }])
self.currentStatus = ko.observable();
self.oldStatus = self.currentStatus();
self.ActiveFarmerID = ko.observable();
self.currentYear = ko.observable();
self.years = ko.observableArray([{ "intYearID": "5", "year": "2014" }, { "intYearID": "6", "year": "2015" }]);
self.businessStartDate = ko.observable();
self.DateFromServer = ko.observable(moment(new Date()).format('L')),
self.individualDOB = ko.observable();
self.businessName = ko.observable();
self.countyOfficeId = ko.observable();
self.individualDetails = ko.observable();
self.indDobOuterHTML = ko.observable();
self.evidenceTypes = ko.observableArray();
self.evidenceItem = function (evidenceData) {
var self = this;
if (evidenceData === null) {
self.EvidenceCategoryID = ko.observable(-1);
self.DateModified = ko.observable(moment(new Date()).format('L'));
self.DateReceipted = ko.observable(moment(new Date()).format('L'));
self.DocReceiptID = ko.observable("");
self.EvidenceID = ko.observable(-1);
self.EvidenceTypeID = ko.observable(-1);
self.Other = ko.observable("");
self.ReceiptedBy = ko.observable("");
//self.RowStatus = ko.observable("I");
self.TrimRecord = ko.observable("");
self.TrimRecordDocReceipt = ko.observable("");
self.UserID = ko.observable('NIGOV\1284535');
self.selectedCategory = ko.observable(6);
}
else {
self.EvidenceCategoryID = ko.observable(6);
self.DateModified = ko.observable(moment(evidenceData.DateModified).format('L'));
self.DateReceipted = ko.observable(moment(evidenceData.DateReceipted).format('L'));
self.DocReceiptID = ko.observable(evidenceData.DocReceiptID);
self.EvidenceID = ko.observable(evidenceData.EvidenceID);
self.EvidenceTypeID = ko.observable(evidenceData.EvidenceTypeID);
self.Other = ko.observable(evidenceData.Other);
self.ReceiptedBy = ko.observable(evidenceData.ReceiptedBy);
self.RowStatus = ko.observable(evidenceData.RowStatus);
self.TrimRecord = ko.observable(evidenceData.TrimRecord);
self.TrimRecordDocReceipt = ko.observable(evidenceData.TrimRecordDocReceipt);
self.UserID = ko.observable(evidenceData.UserID);
self.selectedCategory = ko.observable(6)
}
self.filteredSubCategories = ko.computed(function () {
self.EvidenceCategoryID = self.selectedCategory();
var ret = ko.observableArray();
var filterAll = ko.observableArray();
ret().push({ EvidenceTypeID: -1, EvidenceTypeDescription: "Please Select..." });
if (self.selectedCategory()) {
filterAll = ko.utils.arrayFilter(vm.evidenceTypes(), function (item) {
return item.EvidenceCategoryID === self.selectedCategory();
});
for (var i = 0; i < filterAll.length; i++) {
ret().push(
{
EvidenceTypeID: filterAll[i].EvidenceTypeID,
EvidenceTypeDescription: filterAll[i].EvidenceTypeDescription,
EvidenceCategoryID: filterAll[i].EvidenceCategoryID
});
};
return ret();
}
return [];
}, self);
};
self.NotePad = {
notes: ko.observableArray([
{ DateOfEntry: "01/05/2014", UserName: "John", EntryType: "Change Status", NoteText: "Status Changes to Active(Non Verified)" }
])
};
// Active Farmer Information
self.afi = {
ActiveFarmer: {
ActiveFarmerID: ko.observable(),
BusinessID: ko.observable(),
Year: ko.observable(),
StatusID: ko.observable(),
Status:ko.observable(),
DecisionDate: ko.observable(),
UserID: ko.observable(),
DateModified: ko.observable(),
},
ActiveFarmerEvidence: ko.observableArray(),
NotepadIdentifiers: ko.observableArray()
};
}
public class ActiveFarmerInfo
{
public ActiveFarmerInfo()
{
}
protected override string GetSchemaName()
{
return "ActiveFarmer";
}
[XmlIgnore]
public int ActiveFarmerID { get; set; }
[DataMember, XmlElement]
public ActiveFarmer ActiveFarmer { get; set; }
// To contain the list for Active Farmer Application Evidences based on Active Farmer Id and Year
[DataMember, XmlElement]
public List<Evidence> ActiveFarmerEvidence { get; set; }
public Int32 BusinessId { get; set; }
public Int32 Year { get; set; }
}
All the properties of the view model are knockout observable functions. So calling JSON.stringify to a view model with that kind of properties will not produce valid json. Try changing JSON.strngify to ko.toJSON This function produces valid json string from a knockout view model. Something like this:
var afi = vm.afi;
$.ajax({
type: "POST",
contentType: "application/json",
url: rootcap + "ActiveFarmerService.svc/rest/UpdateFarmer",
data: ko.toJSON(afi),
dataType: "json",
async: true,
cache: false,
success: function (data, textStatus) {
self.populateFarmerDetails(data);
},
error: function (data, status, error) { }
});
Notice the data property of the object passed to $.ajax function.

condition editing using .editable(..) datatables

Im new to datatables, and Im having this issue thats bugging me for a while.
for example, I'm trying to edit the 5th column, but I want to disable it for part of the rows..
is it possible? cause I don't seem to find the way..
$('td:eq('5')', oTable.fnGetNodes()).editable('/'+appName+'/GetGenWidgetTableDataServlet',
{
type : 'text',
tooltip: 'Click to Edit',
indicator: 'Saving...',
placeholder : '',
"callback": function( sValue, y ) {
var aPos = oTable.fnGetPosition( this );
oTable.fnUpdate( sValue, aPos[0], aPos[2],true,true );
},
"submitdata": function ( value, settings ) {
debugger
var iPos = oTable.fnGetPosition( this );
var colPos = iPos[2];
iPos = iPos[0];
if(iPos!=null)
{
var aData = oTable.fnGetData( iPos );
var vRowType = aData[0];
var iId = aData[2];
var moduleID = iId.split("$")[0];
var unitID = iId.split("$")[1];
var processID = iId.split("$")[2];
var riskID = iId.split("$")[3];
var controlID = iId.split("$")[4];
}
return {
"Token": idhref,
"moduleID" :moduleID,
"unitID": unitID,
"processID" :processID ,
"riskID": riskID,
"controlID": controlID,
"rowType":vRowType,
"Action": "saveRow",
"columnName": aoCols[colPos]["Id"]
};
},
"height": "25px",
"width": "50px"
}
We use the datatables editable plugin (https://code.google.com/p/jquery-datatables-editable/ ) and it allows you to set a sReadOnlyCellClass. We set that class in the datatable fnRowCallBack function based on the values in the row.
You could set an "editable" class in your fnRowCallBack
oTable = $('#resultTable').dataTable( {
...
"fnRowCallback": function( nRow, aData, iDisplayIndex ) {
if ( aData["something"] == "This row should be editable" )
{
nRow.className = "editable";
}
return nRow;
}
...
});
and modify your selector to
oTable.$('tr.editable td:eq(5)').editable( ...)

Change Value of a dojo tree node

I'm trying to change the value of a dojo tree to display the correct icon. I was hopping that I could get the object with fetchItemByIdentity() and change the value there but the item is null
_target: null,
_treeModel: null,
constructor: function(target, uuid) {
this._target = target;
this._uuid = uuid;
// from somewhere else the value get's changed
topic.subscribe("questionChanged", lang.hitch(this, function(object, id) {
var item = this._treeModel.fetchItemByIdentity({
identifier: id,
onItem: function(item, request) { alert("item " + item); }
});
}));
},
buildTree: function() {
xhr.get({
// The URL to request
url: er.getAbsoluteUrl("/secure/staticquestion/tree?uuid=" + this._uuid),
handleAs: "json",
headers: {
"Content-Type": "application/json; charset=utf-8"
},
preventCache: 'true',
// The method that handles the request's successful result
load: lang.hitch(this, function(response) {
var rawdata = new Array();
rawdata.push(response);
var store = new ItemFileReadStore({
data: {
identifier: "uuid",
label: "name",
items: rawdata
}
});
this._loadtree(store);
}),
error: function(err, ioArgs) {
errorDialog.show(err.message);
}
});
},
_loadtree: function(store) {
this._treeModel = new TreeStoreModel({
store: store,
query: {
name: 'root'
},
childrenAttrs: [ "children" ],
mayHaveChildren: function(object) {
return object.children.length > 0;
}
});
var tree = new Tree({ // create a tree
model: this._treeModel, // give it the model
showRoot: false,
getIconClass: function(/* dojo.data.Item */item, /* Boolean */opened) {
if (!item || this.model.mayHaveChildren(item)) {
return opened ? "dijitFolderOpened" : "dijitFolderClosed";
} else if (item.comment == 'false') {
return (item.answer == 'YES') ? "dijitLeafNoCommentYes"
: ((item.answer == 'NO') ? "dijitLeafNoCommentNo" : "dijitLeafNoComment");
} else if (item.comment == 'true') {
return (item.answer == 'YES') ? "dijitLeafYes" : ((item.answer == 'NO') ? "dijitLeafNo"
: "dijitLeaf");
}
return "dijitLeaf";
},
}, this._target); // target HTML element's id
tree.on("click", function(object) {
topic.publish("staticQuestionSelected", object);
}, true);
tree.startup();
}
I'm glad for help, thanks!
Ok, I found my issue: I need to use a ItemFileWriteStore and there I can change values with store.setValue(item, attribute, value). The tree updates itself afterwards.

How best to traverse API information with iOS

Is there any easier way of traversing array/dictionaries without creating a lot of separate NSArrays/NSDictionaries? I know you can traverse nested dictionaries with dot notation and value at keypath, but what about when arrays are involved?
For example:
At the moment if I want to get at the object at feed.entry.link[4].href in the API result below, I have to define an array at keypath "feed.entry", then assign its first entry as a dictionary, then define an array at keypath "link" and access its fourth entry as a dictionary, and then access its value at "href".
Is this normal?
received {
encoding = "UTF-8";
feed = {
entry = (
{
author = (
{
name = {
"$t" = swdestiny;
};
uri = {
"$t" = "https://gdata.youtube.com/feeds/api/users/swdestiny";
};
}
);
category = (
{
scheme = "http://schemas.google.com/g/2005#kind";
term = "http://gdata.youtube.com/schemas/2007#video";
},
{
label = Entertainment;
scheme = "http://gdata.youtube.com/schemas/2007/categories.cat";
term = Entertainment;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = Star;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = Wars;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = Episode;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = 3;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = Revenge;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = of;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = the;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = Sith;
}
);
content = {
"$t" = "sw-destiny.net Trailer for Revenge of the Sith";
type = text;
};
"gd$comments" = {
"gd$feedLink" = {
countHint = 1567;
href = "https://gdata.youtube.com/feeds/api/videos/9kdEsZH5ohc/comments";
rel = "http://gdata.youtube.com/schemas/2007#comments";
};
};
"gd$rating" = {
average = "4.7729683";
max = 5;
min = 1;
numRaters = 1132;
rel = "http://schemas.google.com/g/2005#overall";
};
id = {
"$t" = "http://gdata.youtube.com/feeds/api/videos/9kdEsZH5ohc";
};
link = (
{
href = "https://www.youtube.com/watch?v=9kdEsZH5ohc&feature=youtube_gdata";
rel = alternate;
type = "text/html";
},
{
href = "https://gdata.youtube.com/feeds/api/videos/9kdEsZH5ohc/responses";
rel = "http://gdata.youtube.com/schemas/2007#video.responses";
type = "application/atom+xml";
},
{
href = "https://gdata.youtube.com/feeds/api/videos/9kdEsZH5ohc/related";
rel = "http://gdata.youtube.com/schemas/2007#video.related";
type = "application/atom+xml";
},
{
href = "https://m.youtube.com/details?v=9kdEsZH5ohc";
rel = "http://gdata.youtube.com/schemas/2007#mobile";
type = "text/html";
},
{
href = "https://gdata.youtube.com/feeds/api/videos/9kdEsZH5ohc";
rel = self;
type = "application/atom+xml";
}
);
"media$group" = {
"media$category" = (
{
"$t" = Entertainment;
label = Entertainment;
scheme = "http://gdata.youtube.com/schemas/2007/categories.cat";
}
);
"media$content" = (
{
duration = 151;
expression = full;
isDefault = true;
medium = video;
type = "application/x-shockwave-flash";
url = "https://www.youtube.com/v/9kdEsZH5ohc?version=3&f=videos&app=youtube_gdata";
"yt$format" = 5;
},
{
duration = 151;
expression = full;
medium = video;
type = "video/3gpp";
url = "rtsp://v2.cache4.c.youtube.com/CiILENy73wIaGQkXovmRsURH9hMYDSANFEgGUgZ2aWRlb3MM/0/0/0/video.3gp";
"yt$format" = 1;
},
{
duration = 151;
expression = full;
medium = video;
type = "video/3gpp";
url = "rtsp://v2.cache5.c.youtube.com/CiILENy73wIaGQkXovmRsURH9hMYESARFEgGUgZ2aWRlb3MM/0/0/0/video.3gp";
"yt$format" = 6;
}
);
"media$description" = {
"$t" = "sw-destiny.net Trailer for Revenge of the Sith";
type = plain;
};
"media$keywords" = {
"$t" = "Star, Wars, Episode, 3, Revenge, of, the, Sith";
};
"media$player" = (
{
url = "https://www.youtube.com/watch?v=9kdEsZH5ohc&feature=youtube_gdata_player";
}
);
"media$thumbnail" = (
{
height = 360;
time = "00:01:15.500";
url = "http://i.ytimg.com/vi/9kdEsZH5ohc/0.jpg";
width = 480;
},
{
height = 90;
time = "00:00:37.750";
url = "http://i.ytimg.com/vi/9kdEsZH5ohc/1.jpg";
width = 120;
},
{
height = 90;
time = "00:01:15.500";
url = "http://i.ytimg.com/vi/9kdEsZH5ohc/2.jpg";
width = 120;
},
{
height = 90;
time = "00:01:53.250";
url = "http://i.ytimg.com/vi/9kdEsZH5ohc/3.jpg";
width = 120;
}
);
"media$title" = {
"$t" = "Star Wars Episode 3 Revenge of the Sith Trailer";
type = plain;
};
"yt$duration" = {
seconds = 151;
};
};
published = {
"$t" = "2007-05-23T03:31:54.000Z";
};
title = {
"$t" = "Star Wars Episode 3 Revenge of the Sith Trailer";
type = text;
};
updated = {
"$t" = "2012-02-20T17:14:37.000Z";
};
"yt$statistics" = {
favoriteCount = 763;
viewCount = 796719;
};
}
);
xmlns = "http://www.w3.org/2005/Atom";
"xmlns$gd" = "http://schemas.google.com/g/2005";
"xmlns$media" = "http://search.yahoo.com/mrss/";
"xmlns$yt" = "http://gdata.youtube.com/schemas/2007";
};
version = "1.0";
}