more-xrm
Version:
Create more applications using the Microsoft Dynamics Xrm platform, enables querying the dynamics data model from any application.
169 lines (168 loc) • 6.54 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const Query_1 = require("./Query");
function GetQueryXml(query, maxRowCount = 0, format = false) {
const dataQuery = Query_1.GetRootQuery(query);
if (format) {
return formatXml(GetDataQueryXml(dataQuery, maxRowCount));
}
else {
return GetDataQueryXml(dataQuery, maxRowCount);
}
}
exports.default = GetQueryXml;
function GetDataQueryXml(query, maxRowCount) {
var xml = [];
xml.push('<fetch mapping="logical"');
if (maxRowCount > 0) {
xml.push(` count="${maxRowCount}"`);
}
xml.push('>');
xml.push(`<entity name="${query.EntityName}" >`);
xml.push(getQueryXml(query));
xml.push('</entity>');
xml.push('</fetch>');
return xml.join('');
}
function getQueryXml(query) {
const xml = [];
query.Attributes.forEach(attribute => {
if (query.Alias[attribute]) {
xml.push(`<attribute name="${attribute}" alias="${query.Alias[attribute]}" />`);
}
else {
xml.push(`<attribute name="${attribute}" />`);
}
});
query.OrderBy.forEach(attribute => {
if (attribute.indexOf('_') == 0) {
xml.push(`<order attribute="${attribute.slice(1)}" descending="true" />`);
}
else {
xml.push(`<order attribute="${attribute}" />`);
}
});
if (query.Conditions.length > 0) {
var hasOrCondition = false;
var filters = [];
filters.push('<filter type="and">');
for (var filter of query.Conditions) {
if (filter && filter.hasOwnProperty('length')) {
hasOrCondition = true;
var conditions = filter;
filters.push('</filter>');
filters.push('<filter type="or">');
for (var condition of conditions) {
filters.push(getConditionXml(condition));
}
filters.push('</filter>');
filters.push('<filter type="and">');
}
else {
filters.push(getConditionXml(filter));
}
}
filters.push('</filter>');
if (hasOrCondition) {
filters.unshift('<filter type="and">');
filters.push('</filter>');
}
var skipNextFilter;
for (var i = 0; i < filters.length; i++) {
if (filters[i] && filters[i + 1] && filters[i].indexOf('<filter') > -1 && filters[i + 1].indexOf('/filter>') > -1) {
skipNextFilter = true;
}
else if (!skipNextFilter) {
xml.push(filters[i]);
}
else {
skipNextFilter = false;
}
}
}
if (query.Joins) {
for (var join of query.Joins) {
xml.push(`<link-entity name="${join.EntityName}" alias="${join.JoinAlias}" from="${join.JoinFromAttributeName}" to="${join.JoinToAttributeName}" link-type="${join.IsOuterJoin ? 'outer' : 'inner'}">`);
xml.push(getQueryXml(join));
xml.push('</link-entity>');
}
}
return xml.join('\n');
}
function getConditionXml(condition) {
var xml = [];
if (condition.AttributeName.indexOf('.') > -1) {
condition.AttributeName = `${condition.AttributeName.split('.')[1]}" entityname="${condition.AttributeName.split('.')[0]}`;
}
if (condition.Values && condition.Values.length > 0) {
if (condition.Values.length > 1) {
xml.push(`<condition attribute="${condition.AttributeName}" operator="${condition.Operator}">`);
for (var value of condition.Values) {
xml.push(`<value>${encodeValue(value)}</value>`);
}
xml.push('</condition>');
}
else {
xml.push(`<condition attribute="${condition.AttributeName}" operator="${condition.Operator}" value="${encodeValue(condition.Values[0])}" />`);
}
}
else {
xml.push(`<condition attribute="${condition.AttributeName}" operator="${condition.Operator}" />`);
}
return xml.join('\n');
}
function encodeValue(value) {
if (value === 0)
return '0';
if (value === true)
return 'true';
if (value === false)
return 'false';
if (!value)
return '';
if (typeof (value.toISOString) === 'function')
return value.toISOString();
return xmlEncode(value.toString());
}
function xmlEncode(text) {
if (text && typeof (text) === 'string') {
text = text.replace(/&/g, '&');
text = text.replace(/\"/g, '"');
text = text.replace(/\'/g, ''');
text = text.replace(/</g, '<');
text = text.replace(/>/g, '>');
}
return text;
}
function formatXml(xmlString) {
var indent = "\t";
var tabs = ""; //store the current indentation
return xmlString.replace(/\s*<[^>\/]*>[^<>]*<\/[^>]*>|\s*<.+?>|\s*[^<]+/g, //pattern to match nodes (angled brackets or text)
function (m, i) {
m = m.replace(/^\s+|\s+$/g, ""); //trim the match just in case
if (i < 38 && /^<[?]xml/.test(m))
return m + "\n"; //if the match is a header, ignore it
if (/^<[/]/.test(m)) //if the match is a closing tag
{
tabs = tabs.replace(indent, ""); //remove one indent from the store
m = tabs + m; //add the tabs at the beginning of the match
}
else if (/<.*>.*<\/.*>|<.*[^>]\/>/.test(m)) //if the match contains an entire node
{
//leave the store as is or
m = m.replace(/(<[^\/>]*)><[\/][^>]*>/g, "$1 />"); //join opening with closing tags of the same node to one entire node if no content is between them
m = tabs + m; //add the tabs at the beginning of the match
}
else if (/<.*>/.test(m)) //if the match starts with an opening tag and does not contain an entire node
{
m = tabs + m; //add the tabs at the beginning of the match
tabs += indent; //and add one indent to the store
}
else //if the match contain a text node
{
m = tabs + m; // add the tabs at the beginning of the match
}
//return m+"\n";
return "\n" + m; //content has additional space(match) from header
});
}