jsonix - How to create an element with prefix and without namespace? - namespaces

I'm required to send an XML with the following elements:
<return>
<getrooms>true</getrooms>
<filters xmlns:a="http://some.com/xsd/atomicCondition" xmlns:c="http://some.com/xsd/complexCondition">
<city></city>
<country></country>
<c:condition>
<a:condition>
<fieldname>fieldName</fieldname>
<fieldtest>fieldTest</fieldtest>
<fieldvalues>
<fieldvalue>fieldValue</fieldvalue>
</fieldvalues>
</a:condition>
<operator>operator</operator>
<a:condition>
<fieldname>fieldName</fieldname>
<fieldtest>fieldTest</fieldtest>
<fieldvalues>
<fieldvalue>fieldValue</fieldvalue>
</fieldvalues>
</a:condition>
</c:condition>
</filters>
<resultsperpage></resultsperpage>
<page></page>
</return>
I'm having difficulty forming the "c:condition" and "a:condition" Qname using Jsonix. Both Qname contains a Prefix but don't have the namespace.
My current code is:
{
type: 'element',
name: 'ccondition',
elementName: {
localPart: 'condition',
prefix: 'c',
namespaceURI: 'c'
},
typeInfo: 'DOXML.ComplexCondition'
},
This will result in the following:
<c:condition xmlns:c="c">
Anyone knows how to use Jsonix to generate the required Qname - "c:condition" that is without the namespaceURI?

In your example, the prefix c is actually bound to the namespace http://some.com/xsd/complexCondition in this line:
<filters xmlns:a="http://some.com/xsd/atomicCondition" xmlns:c="http://some.com/xsd/complexCondition">
Both you prefixes a und c are bound to non-empty namespaces within the scope of the filters element.
So you should actually do:
{
type: 'element',
name: 'ccondition',
elementName: {
localPart: 'condition',
prefix: 'c',
namespaceURI: 'http://some.com/xsd/complexCondition'
},
typeInfo: 'DOXML.ComplexCondition'
}
I think you should be able to map to the empty namespace with namespaceURI: '', but this is not what you need in your case, if I see it correctly.

Related

SailsJS Blueprints going haywire

I had been working on an app using SailsJS v0.12. The app was working as expected. But, for some modules, it made sense to upgrade to v1.0 because it offered some great features, and the website implied (or seemed so) that the upgrade process was simple.
That wasn't the case. After a day of tedious refactoring, I succeeded in building the existing code and started working on the new modules. The problem to focus on began here.
I ran the functions as I did previously in POSTman and I stopped getting response. To check individual models, I tried using the Blueprints. Since no structural changes were made to any of the models, this should've worked. But I couldn't get any response in POST; GET was still working. I logged off for a break and then made a GET request to a model with some associations (working perfectly before).
I got this response
UsageError: Invalid populate(s). Details: Could not populate
customer because of ambiguous usage. This is a singular ("model")
association, which means it never refers to more than one associated
record. So passing in subcriteria (i.e. as the second argument to
.populate()) is not supported for this association, since it
generally wouldn't make any sense. But that's the trouble-- it looks
like some sort of a subcriteria (or something) was provided! (Note
that subcriterias consisting ONLY of omit or select are a special
case that does make sense. This usage will be supported in a future
version of Waterline.)
Here's what was passed in: { limit: 30 }
The complete JSON response is:
{
"stack": "UsageError: Invalid populate(s).\nDetails:\n Could not populate `customer` because of ambiguous usage. This is a singular (\"model\") association, which means it never refers to more than _one_ associated record. So passing in subcriteria (i.e. as the second argument to `.populate()`) is not supported for this association, since it generally wouldn't make any sense. But that's the trouble-- it looks like some sort of a subcriteria (or something) _was_ provided!\n(Note that subcriterias consisting ONLY of `omit` or `select` are a special case that _does_ make sense. This usage will be supported in a future version of Waterline.)\n\nHere's what was passed in:\n{ limit: 30 }\n\n at findRecords (D:\\Dev\\NodeJS\\zingr\\node_modules\\sails\\lib\\hooks\\blueprints\\actions\\find.js:40:21)\n at routeTargetFnWrapper (D:\\Dev\\NodeJS\\zingr\\node_modules\\sails\\lib\\router\\bind.js:181:5)\n at callbacks (D:\\Dev\\NodeJS\\zingr\\node_modules\\express\\lib\\router\\index.js:164:37)\n at param (D:\\Dev\\NodeJS\\zingr\\node_modules\\express\\lib\\router\\index.js:138:11)\n at pass (D:\\Dev\\NodeJS\\zingr\\node_modules\\express\\lib\\router\\index.js:145:5)\n at nextRoute (D:\\Dev\\NodeJS\\zingr\\node_modules\\express\\lib\\router\\index.js:100:7)\n at callbacks (D:\\Dev\\NodeJS\\zingr\\node_modules\\express\\lib\\router\\index.js:167:11)\n at alwaysAllow (D:\\Dev\\NodeJS\\zingr\\node_modules\\sails\\lib\\hooks\\policies\\index.js:224:11)\n at routeTargetFnWrapper (D:\\Dev\\NodeJS\\zingr\\node_modules\\sails\\lib\\router\\bind.js:181:5)\n at callbacks (D:\\Dev\\NodeJS\\zingr\\node_modules\\express\\lib\\router\\index.js:164:37)\n at param (D:\\Dev\\NodeJS\\zingr\\node_modules\\express\\lib\\router\\index.js:138:11)\n at pass (D:\\Dev\\NodeJS\\zingr\\node_modules\\express\\lib\\router\\index.js:145:5)\n at nextRoute (D:\\Dev\\NodeJS\\zingr\\node_modules\\express\\lib\\router\\index.js:100:7)\n at callbacks (D:\\Dev\\NodeJS\\zingr\\node_modules\\express\\lib\\router\\index.js:167:11)\n at module.exports (D:\\Dev\\NodeJS\\zingr\\node_modules\\sails\\lib\\hooks\\cors\\clear-headers.js:14:3)\n at routeTargetFnWrapper (D:\\Dev\\NodeJS\\zingr\\node_modules\\sails\\lib\\router\\bind.js:181:5)\n at callbacks (D:\\Dev\\NodeJS\\zingr\\node_modules\\express\\lib\\router\\index.js:164:37)\n at param (D:\\Dev\\NodeJS\\zingr\\node_modules\\express\\lib\\router\\index.js:138:11)\n at pass (D:\\Dev\\NodeJS\\zingr\\node_modules\\express\\lib\\router\\index.js:145:5)\n at nextRoute (D:\\Dev\\NodeJS\\zingr\\node_modules\\express\\lib\\router\\index.js:100:7)\n at callbacks (D:\\Dev\\NodeJS\\zingr\\node_modules\\express\\lib\\router\\index.js:167:11)\n at sails.router.bind._middlewareType (D:\\Dev\\NodeJS\\zingr\\node_modules\\sails\\lib\\hooks\\csrf\\index.js:148:11)\n at routeTargetFnWrapper (D:\\Dev\\NodeJS\\zingr\\node_modules\\sails\\lib\\router\\bind.js:181:5)\n at callbacks (D:\\Dev\\NodeJS\\zingr\\node_modules\\express\\lib\\router\\index.js:164:37)\n at param (D:\\Dev\\NodeJS\\zingr\\node_modules\\express\\lib\\router\\index.js:138:11)\n at pass (D:\\Dev\\NodeJS\\zingr\\node_modules\\express\\lib\\router\\index.js:145:5)\n at nextRoute (D:\\Dev\\NodeJS\\zingr\\node_modules\\express\\lib\\router\\index.js:100:7)\n at callbacks (D:\\Dev\\NodeJS\\zingr\\node_modules\\express\\lib\\router\\index.js:167:11)\n at _addResViewMethod (D:\\Dev\\NodeJS\\zingr\\node_modules\\sails\\lib\\hooks\\views\\res.view.js:372:3)\n at routeTargetFnWrapper (D:\\Dev\\NodeJS\\zingr\\node_modules\\sails\\lib\\router\\bind.js:181:5)\n at callbacks (D:\\Dev\\NodeJS\\zingr\\node_modules\\express\\lib\\router\\index.js:164:37)\n at param (D:\\Dev\\NodeJS\\zingr\\node_modules\\express\\lib\\router\\index.js:138:11)\n at pass (D:\\Dev\\NodeJS\\zingr\\node_modules\\express\\lib\\router\\index.js:145:5)\n at nextRoute (D:\\Dev\\NodeJS\\zingr\\node_modules\\express\\lib\\router\\index.js:100:7)",
"message": "Invalid populate(s).\nDetails:\n Could not populate `customer` because of ambiguous usage. This is a singular (\"model\") association, which means it never refers to more than _one_ associated record. So passing in subcriteria (i.e. as the second argument to `.populate()`) is not supported for this association, since it generally wouldn't make any sense. But that's the trouble-- it looks like some sort of a subcriteria (or something) _was_ provided!\n(Note that subcriterias consisting ONLY of `omit` or `select` are a special case that _does_ make sense. This usage will be supported in a future version of Waterline.)\n\nHere's what was passed in:\n{ limit: 30 }\n",
"name": "UsageError",
"code": "E_INVALID_POPULATES",
"details": "Could not populate `customer` because of ambiguous usage. This is a singular (\"model\") association, which means it never refers to more than _one_ associated record. So passing in subcriteria (i.e. as the second argument to `.populate()`) is not supported for this association, since it generally wouldn't make any sense. But that's the trouble-- it looks like some sort of a subcriteria (or something) _was_ provided!\n(Note that subcriterias consisting ONLY of `omit` or `select` are a special case that _does_ make sense. This usage will be supported in a future version of Waterline.)\n\nHere's what was passed in:\n{ limit: 30 }"
}
The confusing aspect is that this is only happening locally. The blueprints work perfectly as expected on the deployment (same code, double-checked) hosted on Zeit.co. I have tested this enough times to deduce that this isn't a fault in my models. Nonetheless, here are the models - Bill and Customer:
models\Bill.js
module.exports = {
primaryKey:'id',
attributes: {
createdAt: { type: 'number', autoCreatedAt: true, },
updatedAt: { type: 'number', autoUpdatedAt: true, },
id:{
type:'string',
required:true
},
bill_number:{
type:'string'
},
admin_id:{
type:'string'
},
channel:{
type:'string'
},
amount:{
type:'number'
},
discount:{
type:'number',
defaultsTo:0
},
order_date:{
type: 'number'
},
status:{
type:'string',
isIn:['generated', 'settled', 'canceled'],
defaultsTo:'generated'
},
type:{
type:'string',
isIn:['dine-in', 'take-away', 'delivery', 'logistics-delivery'],
required:true
},
logisticsPartner:{
type:'string',
defaultsTo:'phone'
},
//association
customer:{
model:'customer'
},
store:{
model:'store'
},
orderContents:{
collection:'billmapping',
via:'bill'
},
transactions:{
collection:'transaction',
via:'bill'
}
}
};
models\Customer.js
module.exports = {
attributes: {
createdAt: { type: 'number', autoCreatedAt: true, },
updatedAt: { type: 'number', autoUpdatedAt: true, },
id: { type: 'number', autoIncrement: true}, // <-- for SQL databases
name:{
type:'string'
},
number:{
type:'string',
unique:true
},
email:{
type:'string',
unique:true
},
age:{
type:'number'
}
}
};
This issue has had me pulling my hair out for 8 hours now. Can anybody shed some light or share some suggestions?
Thanks in advance.

Accessing an included object

I have the following JSON Object, which is the result of a loopback model (Classifications), with a relationship with another model (Labels).
My call to get the classifications is:
modClassification.findOne({
where: { id: classificationid },
include: 'labels' },
function( err, classification ){ ...
And this returns classification with something like
{ id: 'b01',
title: 'population',
country_id: 1,
labels:
[ { column_id: 'b1',
classification_id: 'b01',
classification_title: 'population',
dsporder: 1,
label: 'Total_Persons_Males',
country_id: 1,
id: 1 },
{ column_id: 'b2',
classification_id: 'b01',
classification_title: 'population',
dsporder: 2,
label: 'Total_Persons_Females',
country_id: 1,
id: 2 } ] }
which is what I would expect.
I now need to loop over the labels and access it's properties, but this is where I am stuck.
classification.labels[0] = undefined..
I have tried looping, each and whatever I can find online, but can't seem to get to each labels properties.
Can someone tell me what I am doing wrong/need to do?
Thanks
When you are including related models inside a findOne call, you need to JSONify the result before accessing the related records:
classification = classification.toJSON()
Then you should be able to access the included label items as you expect.
See https://docs.strongloop.com/display/public/LB/Include+filter, specifically the "Access included objects" section.
Note this does not work the same when you retrieve more than one result in an array. In that case you'll need to perform toJSON() on each item in the array.

How to retrieve parent document based on subdocument values in Mongoose?

I have the following schema's:
var Child = new mongoose.Schema({
'field': String,
'value': String
});
var Parent = new mongoose.Schema({
'name': String,
'children': [ Child ]
});
I want to return the Parent for which one of the Child's corresponds to the following JSON object:
{ 'field': 'Family Name', 'value': 'Smith' }
I have tried this:
Parent.findOne({ 'children': { 'field': 'Family Name', 'value': 'Smith' } }, fn ...)
but it keeps on retrieving null.
EDIT:
Testing through the Mongo shell extension, I found out that the Child sub-documents have their own _id's. If I add that _id to the query, it fetches the parent document. Now, I don't know in advance what that child id will be. So: how can I remove it from the sub-document query? (In other words, the above query literally looks for a JSON object with only two properties, while the sub-documents have three)
My environment is: Node.js, Mongoose, MongoDB
It seems the $elemMatch is the query operator to solve this problem. The actual query should be written as follows:
Parent.findOne({ 'children': { $elemMatch: { 'field': 'Family Name', 'value': 'Smith' } } }, fn ...)
Is there a reason you use field, value structure on the child documents? It would be easier to simply use the key as the field, like {"FamilyName": "Smith"}. This would allow something like:
Parent.findOne({'children.FamilyName': 'Smith'}, function(err, doc){...});

Sencha Touch 2 read values from key AND value from nested JSON

I am trying to load some JSON, in which I store a lot of variables about some 100 anaesthetic drugs for pediatric patients.
The actual values get calculated before from patient's weight, age etc.:
Example:
var propofolInductionTitle = propofolName + ' ' + propofol0PercentConcentration + '- Induktion';
var propofol0InductionDosageMG = (Math.round(kg * 2 * 10) / 10) + ' - ' + (Math.round(kg * 5 * 10) / 10);
I then create my drug as a block of json consisting of the variables I need which are later to be replaced by the calculated values. I specifically try to avoid Strings in the JSON to allow for easier localization to english and french when all variables are defined in the math block.
var hypnotikaJSON = {
"thiopentalTitle": [
{"thiopentalBrandName": ""},
{"vialContentTitle": "thiopentalVialContent"},
{"solutionTitle": "thiopentalSolution"},
{"concentrationTitle": "thiopentalConcentration"},
{"dosageString": "thiopentalDosageString"},
{"atWeight": "thiopentalDosageMG"},
{"thiopentalAtConcentration": "thiopentalDosageML"}
],
"propofolInductionTitle": [
{"propofolInductionBrandName": ""},
{"propofolVialContentTitle": "propofolInductionVialContent"},
{"propofolSolutionTitle": "propofolSolution"},
{"propofolConcentrationTitle": "propofolInductionConcentration"},
{"propofolInductionDosageStringTitle": "propofolInductionDosageString"},
{"atWeight": "propofolInductionDosageMG"},
{"propofolAtInductionConcentration": "propofolInductionDosageML"}
],
"propofolSedationTitle": [
{"propofolSedationBrandName":""},
{"propofolVialContentTitle":"propofolSedationVialContent"},
{"propofolSolutionTitle":"propofolSolution"},
{"propofolConcentrationTitle":"propofolSedationConcentration"},
{"propofolSedationDosageStringTitle":"propofolSedationDosageString"},
{"atWeight":"propofolSedationDosageMG"},
{"propofolAtSedationConcentration":"propofolSedationDosageML"}
],
"laryngealMaskTitle": [
{"laryngealMaskSizeTitle":"laryngealMaskSize"},
{"laryngealMaskCuffSizeTitle":"laryngealMaskCuffSize"},
{"laryngealMaskBiggestETTTitle":"laryngealMaskBiggestETT"},
{"laryngealMaskBronchoscopeSizeTitle":"laryngealMaskBronchoscopeSize"}
]
};
My specific need is that the JSON reader has to give me the key AND value of each object as I need both to populate a template. The reason ist that the fields for the drugs are different in parts. Some have additional routes of administration so I have another key:value pair a different drug doesnt have. Some are given both as bolus and per drip, some arent. So no convenient json structure ist possible.
I found an answer by rdougan here that partly allowed me to do just that:
Model:
Ext.define('my.model.Drug', {
extend: 'Ext.data.Model',
config: {
fields: ['name', 'value']
}
});
Custom Json Reader:
Ext.define('Ext.data.reader.Custom', {
extend: 'Ext.data.reader.Json',
alias: 'reader.custom',
getRoot: function (data) {
if (this.rootAccessor) {
data = this.rootAccessor.call(this, data);
}
var values = [],
name;
for (name in data) {
values.push({
name: name,
value: data[name]
});
}
return values;
}
});
Store:
var store = Ext.create('Ext.data.Store', {
fields: ['name', 'value'],
data: hypnotikaJSON,
autoLoad: true,
proxy: {
type: 'memory',
reader: {
type: 'custom'
}
}
});
Panel:
this.viewport = new Ext.Panel({
fullscreen: true,
layout: 'fit',
items: [{
xtype: 'list',
itemTpl: '<p class="description">{name}</p><p class ="values">{value}</p>',
store: store
}]
});
Unfortunately I'm a physician and no programmer, and after a lot of reading I cant find out to apply this to a nested JSON. The custom reader seems to only go for the first level.
I could do it without a reader, without a store with just a lot of plan html around each entry, that has proven to be very very slow though so I would like to avoid it while updating from Sencha Touch 1.1. and better do it right this time.
Could you please point me to a way to parse this ugly data structure?
Thank you
I don't know much about extending JSON readers, so just guessing, but maybe you are supposed override the 'read' method? Then you can go over the JSON as you wish
Also, if you have control over the JSON you should consider changing it.
Usually, the keys in JSON should be the same throughout all items in the array.
keys are not data, they are metadata.
So, if you do have different properties between different drugs, then something like this might be a solution:
[{
name: 'Propofol 1%',
properties: [
{title: 'induction', value: '22-56g'},
{title: 'Sedation', value: '22'},
etc.
]},
{name: 'nextDrug'}
etc..

Filtering a comboxes remote store locally in ExtJs

I have an ExtJs combobox. Its store loaded using JSON (using MyStore class below). I want to load all the values to the store, and then filter them with the text entered in the combo's textfield (preferably using the typeAhead feature).
The problem is that I want to do the filtering on the client side (combo's mode property is 'remote', by default). I don't want my combo to reload its store every time I type something.
How can I do that?
Thanks.
Here's my store class :
MyStore = Ext.extend(Ext.data.JsonStore, {
constructor: function(jsonUrl, storeId, id, description, isAutoLoad, cfg) {
cfg = cfg || {};
GenericStore.superclass.constructor.call(this, Ext.apply({
storeId: storeId,
root: 'result',
url: jsonUrl,
autoLoad: isAutoLoad,
fields: [
{
name: id
},
{
name: description
}
]
}, cfg));
}
});
And the combo :
xtype: 'combo',
fieldLabel: 'The Combo',
width: 150,
store: myStoreData,
valueField: 'id',
displayField: 'name',
minChars : 0,
editable : false,
itemId : 'my-combo'
To achieve this you must:
Construct MyStore class with "isAutoLoad" config option as "true"
In your combobox config set the "mode" config option to "local" (see Built the combo config code bellow for another config)
Here is my short example:
Construct myStoreData variable
var myStoreData = new MyStore({
autoLoad: true, //so the store will load automatically
...any_other_config_option...
});
Built the combo config
{
xtype: 'combo',
fieldLabel: 'The Combo',
width: 150,
store: myStoreData,
// myStoreData is already loaded before as it have 'autoLoad' config set to true
// and act as localstore to populate the combo box item
// when the combo "mode" config set to 'local'
valueField: 'id',
displayField: 'name',
minChars : 0,
editable : true, //before was editable : false,
itemId : 'my-combo',
mode: 'local', // by default this was mode: 'remote'
typeAhead: true // by default this was typeAhead: false
}
You will want to use the store.filter() method. You can use this to use user-entered information to filter your store that the combo box uses. This is taken from the ExtJS API documentation for data.store.
store.filter([
{
property : 'name',
value : 'Ed',
anyMatch : true, //optional, defaults to true
caseSensitive: true //optional, defaults to true
},
//filter functions can also be passed
{
fn : function(record) {
return record.get('age') == 24
},
scope: this
}
]);
In my case I had to add the config option lastQuery:'' to the combo.
explanation : http://progex.wordpress.com/2010/03/26/extjs-combo-dropdown-does-not-filter-on-first-trigger/
Add listener to your store on 'load' event, do filtering, by removing or flagging records, if removing it is clear load to combo component, if flagging you need to recognize those flaggs in combo and display or not...
It hard to go with more details if I do not see your code for store and combo, so I can give you only general idea