XmlReader.js
上传用户:dawnssy
上传日期:2022-08-06
资源大小:9345k
文件大小:9k
源码类别:

JavaScript

开发平台:

JavaScript

  1. /*!
  2.  * Ext JS Library 3.1.0
  3.  * Copyright(c) 2006-2009 Ext JS, LLC
  4.  * licensing@extjs.com
  5.  * http://www.extjs.com/license
  6.  */
  7. /**
  8.  * @class Ext.data.XmlReader
  9.  * @extends Ext.data.DataReader
  10.  * <p>Data reader class to create an Array of {@link Ext.data.Record} objects from an XML document
  11.  * based on mappings in a provided {@link Ext.data.Record} constructor.</p>
  12.  * <p><b>Note</b>: that in order for the browser to parse a returned XML document, the Content-Type
  13.  * header in the HTTP response must be set to "text/xml" or "application/xml".</p>
  14.  * <p>Example code:</p>
  15.  * <pre><code>
  16. var Employee = Ext.data.Record.create([
  17.    {name: 'name', mapping: 'name'},     // "mapping" property not needed if it is the same as "name"
  18.    {name: 'occupation'}                 // This field will use "occupation" as the mapping.
  19. ]);
  20. var myReader = new Ext.data.XmlReader({
  21.    totalProperty: "results", // The element which contains the total dataset size (optional)
  22.    record: "row",           // The repeated element which contains row information
  23.    idProperty: "id"         // The element within the row that provides an ID for the record (optional)
  24.    messageProperty: "msg"   // The element within the response that provides a user-feedback message (optional)
  25. }, Employee);
  26. </code></pre>
  27.  * <p>
  28.  * This would consume an XML file like this:
  29.  * <pre><code>
  30. &lt;?xml version="1.0" encoding="UTF-8"?>
  31. &lt;dataset>
  32.  &lt;results>2&lt;/results>
  33.  &lt;row>
  34.    &lt;id>1&lt;/id>
  35.    &lt;name>Bill&lt;/name>
  36.    &lt;occupation>Gardener&lt;/occupation>
  37.  &lt;/row>
  38.  &lt;row>
  39.    &lt;id>2&lt;/id>
  40.    &lt;name>Ben&lt;/name>
  41.    &lt;occupation>Horticulturalist&lt;/occupation>
  42.  &lt;/row>
  43. &lt;/dataset>
  44. </code></pre>
  45.  * @cfg {String} totalProperty The DomQuery path from which to retrieve the total number of records
  46.  * in the dataset. This is only needed if the whole dataset is not passed in one go, but is being
  47.  * paged from the remote server.
  48.  * @cfg {String} record The DomQuery path to the repeated element which contains record information.
  49.  * @cfg {String} record The DomQuery path to the repeated element which contains record information.
  50.  * @cfg {String} successProperty The DomQuery path to the success attribute used by forms.
  51.  * @cfg {String} idPath The DomQuery path relative from the record element to the element that contains
  52.  * a record identifier value.
  53.  * @constructor
  54.  * Create a new XmlReader.
  55.  * @param {Object} meta Metadata configuration options
  56.  * @param {Object} recordType Either an Array of field definition objects as passed to
  57.  * {@link Ext.data.Record#create}, or a Record constructor object created using {@link Ext.data.Record#create}.
  58.  */
  59. Ext.data.XmlReader = function(meta, recordType){
  60.     meta = meta || {};
  61.     // backwards compat, convert idPath or id / success
  62.     Ext.applyIf(meta, {
  63.         idProperty: meta.idProperty || meta.idPath || meta.id,
  64.         successProperty: meta.successProperty || meta.success
  65.     });
  66.     Ext.data.XmlReader.superclass.constructor.call(this, meta, recordType || meta.fields);
  67. };
  68. Ext.extend(Ext.data.XmlReader, Ext.data.DataReader, {
  69.     /**
  70.      * This method is only used by a DataProxy which has retrieved data from a remote server.
  71.      * @param {Object} response The XHR object which contains the parsed XML document.  The response is expected
  72.      * to contain a property called <tt>responseXML</tt> which refers to an XML document object.
  73.      * @return {Object} records A data block which is used by an {@link Ext.data.Store} as
  74.      * a cache of Ext.data.Records.
  75.      */
  76.     read : function(response){
  77.         var doc = response.responseXML;
  78.         if(!doc) {
  79.             throw {message: "XmlReader.read: XML Document not available"};
  80.         }
  81.         return this.readRecords(doc);
  82.     },
  83.     /**
  84.      * Create a data block containing Ext.data.Records from an XML document.
  85.      * @param {Object} doc A parsed XML document.
  86.      * @return {Object} records A data block which is used by an {@link Ext.data.Store} as
  87.      * a cache of Ext.data.Records.
  88.      */
  89.     readRecords : function(doc){
  90.         /**
  91.          * After any data loads/reads, the raw XML Document is available for further custom processing.
  92.          * @type XMLDocument
  93.          */
  94.         this.xmlData = doc;
  95.         var root    = doc.documentElement || doc,
  96.             q       = Ext.DomQuery,
  97.             totalRecords = 0,
  98.             success = true;
  99.         if(this.meta.totalProperty){
  100.             totalRecords = this.getTotal(root, 0);
  101.         }
  102.         if(this.meta.successProperty){
  103.             success = this.getSuccess(root);
  104.         }
  105.         var records = this.extractData(q.select(this.meta.record, root), true); // <-- true to return Ext.data.Record[]
  106.         // TODO return Ext.data.Response instance.  @see #readResponse
  107.         return {
  108.             success : success,
  109.             records : records,
  110.             totalRecords : totalRecords || records.length
  111.         };
  112.     },
  113.     /**
  114.      * Decode a json response from server.
  115.      * @param {String} action [{@link Ext.data.Api#actions} create|read|update|destroy]
  116.      * @param {Object} response HTTP Response object from browser.
  117.      * @return {Ext.data.Response} response Returns an instance of {@link Ext.data.Response}
  118.      */
  119.     readResponse : function(action, response) {
  120.         var q   = Ext.DomQuery,
  121.         doc     = response.responseXML;
  122.         // create general Response instance.
  123.         var res = new Ext.data.Response({
  124.             action: action,
  125.             success : this.getSuccess(doc),
  126.             message: this.getMessage(doc),
  127.             data: this.extractData(q.select(this.meta.record, doc) || q.select(this.meta.root, doc), false),
  128.             raw: doc
  129.         });
  130.         if (Ext.isEmpty(res.success)) {
  131.             throw new Ext.data.DataReader.Error('successProperty-response', this.meta.successProperty);
  132.         }
  133.         // Create actions from a response having status 200 must return pk
  134.         if (action === Ext.data.Api.actions.create) {
  135.             var def = Ext.isDefined(res.data);
  136.             if (def && Ext.isEmpty(res.data)) {
  137.                 throw new Ext.data.JsonReader.Error('root-empty', this.meta.root);
  138.             }
  139.             else if (!def) {
  140.                 throw new Ext.data.JsonReader.Error('root-undefined-response', this.meta.root);
  141.             }
  142.         }
  143.         return res;
  144.     },
  145.     getSuccess : function() {
  146.         return true;
  147.     },
  148.     /**
  149.      * build response-data extractor functions.
  150.      * @private
  151.      * @ignore
  152.      */
  153.     buildExtractors : function() {
  154.         if(this.ef){
  155.             return;
  156.         }
  157.         var s       = this.meta,
  158.             Record  = this.recordType,
  159.             f       = Record.prototype.fields,
  160.             fi      = f.items,
  161.             fl      = f.length;
  162.         if(s.totalProperty) {
  163.             this.getTotal = this.createAccessor(s.totalProperty);
  164.         }
  165.         if(s.successProperty) {
  166.             this.getSuccess = this.createAccessor(s.successProperty);
  167.         }
  168.         if (s.messageProperty) {
  169.             this.getMessage = this.createAccessor(s.messageProperty);
  170.         }
  171.         this.getRoot = function(res) {
  172.             return (!Ext.isEmpty(res[this.meta.record])) ? res[this.meta.record] : res[this.meta.root];
  173.         }
  174.         if (s.idPath || s.idProperty) {
  175.             var g = this.createAccessor(s.idPath || s.idProperty);
  176.             this.getId = function(rec) {
  177.                 var id = g(rec) || rec.id;
  178.                 return (id === undefined || id === '') ? null : id;
  179.             };
  180.         } else {
  181.             this.getId = function(){return null;};
  182.         }
  183.         var ef = [];
  184.         for(var i = 0; i < fl; i++){
  185.             f = fi[i];
  186.             var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name;
  187.             ef.push(this.createAccessor(map));
  188.         }
  189.         this.ef = ef;
  190.     },
  191.     /**
  192.      * Creates a function to return some particular key of data from a response.
  193.      * @param {String} key
  194.      * @return {Function}
  195.      * @private
  196.      * @ignore
  197.      */
  198.     createAccessor : function(){
  199.         var q = Ext.DomQuery;
  200.         return function(key) {
  201.             switch(key) {
  202.                 case this.meta.totalProperty:
  203.                     return function(root, def){
  204.                         return q.selectNumber(key, root, def);
  205.                     }
  206.                     break;
  207.                 case this.meta.successProperty:
  208.                     return function(root, def) {
  209.                         var sv = q.selectValue(key, root, true);
  210.                         var success = sv !== false && sv !== 'false';
  211.                         return success;
  212.                     }
  213.                     break;
  214.                 default:
  215.                     return function(root, def) {
  216.                         return q.selectValue(key, root, def);
  217.                     }
  218.                     break;
  219.             }
  220.         };
  221.     }(),
  222.     /**
  223.      * extracts values and type-casts a row of data from server, extracted by #extractData
  224.      * @param {Hash} data
  225.      * @param {Ext.data.Field[]} items
  226.      * @param {Number} len
  227.      * @private
  228.      * @ignore
  229.      */
  230.     extractValues : function(data, items, len) {
  231.         var f, values = {};
  232.         for(var j = 0; j < len; j++){
  233.             f = items[j];
  234.             var v = this.ef[j](data);
  235.             values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue, data);
  236.         }
  237.         return values;
  238.     }
  239. });