📄 xmltools.js
字号:
for (var i = 0; i < this.xmlDOMConstructors.length; i++) { try { var cons = this.xmlDOMConstructors[i]; parser = new ActiveXObject(cons); if (parser) { this.logInfo("Using XML DOM constructor: " + cons); this._xmlDOMConstructor = cons; break; } } catch (e) { } } if (!parser) { this.logWarn("Couldn't create XML DOM parser - tried the following" +" constructors: "+this.echoAll(this.xmlDOMConstructors)); } } return parser;},//> @classMethod XMLTools.nativeXMLAvailable() //// Returns true if the current browser exposes an XML parser that can be used for SmartClient// XML operations like web service bindings and XML processing. See// +link{group:platformDependencies} for more information on when the XML parser may not// available and what features are impacted as a result.//// @return (boolean) true if native XML processing is available, false otherwise.//// @visibility external//< nativeXMLAvailable : function () { if (isc.Browser.isSafari && !isc.Browser.isApollo && (isc.Browser.safariVersion < 522)) return false; return this._parser != null || this.getXMLParser() != null; },_warnIfNativeXMLUnavailable : function (featureName) { if (this.nativeXMLAvailable() || !this.logIsWarnEnabled()) return false; var message = "Feature " + featureName + " requires a native XML parser which is " + "not available "; if (isc.Browser.isSafari) { message += "because this version of Safari does not support native XML processing."; } else { // IE ActiveX message += "because ActiveX is currently disabled."; } message += " Please see the 'Features requiring ActiveX or Native support'" +" topic in the client-side reference under Client Reference/System" +" for more information"; this.logWarn(message); return true;},// Access / serverToJS// ---------------------------------------------------------------------------------------// call the server to do an XML2JS conversion, evals resultserverToJS : function (xmlString, callback, evalVars) { isc.DMI.callBuiltin({ methodName: "xmlToJS", callback: callback, arguments: xmlString, requestParams: { evalVars: evalVars, evalResult: true } });},// calls the server to do an XML2JS conversion, returns string as 'data' in callbacktoJSCode : function (xmlString, callback) { isc.DMI.callBuiltin("xmlToJS", xmlString, callback);},// convert an XML or DOM element to a JavaScript object. Attributes and subelements become// properties. Note: if nodeNames collide, last one wins. Also note that getElementsByTagName(*)// returns all children nodes recursively - not just the immediate children. So you get a flat// representation of a potentially nested object. See the more expensive toJS() for a nested// result._$star : "*",elementToObject : function (element) { if (element == null) return null; var object = this.getAttributes(element); // tranform subelements to properties var children = element.getElementsByTagName(this._$star); for (var i = 0; i < children.length; i++) { var child = children[i]; object[child.tagName] = this.getElementText(child); } return object;},_$colon : ":",// return the non-namespace-prefixed tagName, or #text / #comment / #cdata-section for text// nodesgetLocalName : function (node) { // All: tagName/nodeName prefixed // Moz: localName is non-prefix'd if (!isc.Browser.isIE) { var localName = node.localName; if (localName == null) return node.nodeName; // for #text nodes in Moz return localName; } var name = node.nodeName, colonIndex = name.indexOf(this._$colon); if (colonIndex != -1) return name.substring(colonIndex + 1); return name;},//> @classMethod XMLTools.toJS()// Translates an XML fragment to JavaScript collections. This method works just like the// server-side method XML.toJS(Element, Writer):// <ul>// <li> Elements become JavaScript Objects with each attribute becoming a property// <li> Subelements with just text (no child elements or attributes) become properties// <li> Subelements with child elements or attributes become sub objects// </ul>// For example, if you pass the following fragment to this method:// <pre>// <foo bar="zoo">// <x>y</x>// </foo>// </pre>// You will get back the following JS structure: // <pre>// { bar:"zoo", x:"y"}// </pre>// All atomic property values will be of String type. Use +link{DataSource.recordsFromXML()}// to do schema-driven XML to JS transform, which can produce correctly typed values.// // @param element (XMLElement or XMLDocument) The element to tranform to JS// @return (Object) The resulting JavaScript collection.//// @visibility external// @example xmlServerValidationErrors//<// deep transform XML to JS. calls itself recursively. subelements with just the value get// collapsed, key collisions are turned into arrays. There are almost certainly still// differences from server-side transform but none are known at this time.//// You can supply an array of fieldNames to look for ("attrMask") - this limits the output data// to those fields, and is substantially faster in IE for an XML representation that uses lots// of attributes rather than subelements_$List : "List",_$xmlToJS : "xmlToJS",toJS : function (element, attrMask, dataSource, widgetXML, context) { if (element == null) return null; if (isc.isAn.XMLDoc(element)) element = element.nativeDoc; if (element.documentElement) element = element.documentElement; context = context || isc.emptyObject; //this.logWarn("toJS: " + this.echoLeaf(element) + // ", attrs: " + attrMask + // ", dataSource: " + dataSource); // handle arrays of elements if (isc.isAn.Array(element)) { var results = []; for (var i = 0; i < element.length; i++) { results[i] = this.toJS(element[i], attrMask, dataSource, widgetXML, context); } return results; } var object, fieldNames; // check explicit type var type = this.getExplicitType(element); if (widgetXML || !dataSource || (dataSource && isc.DS.get(type) == null)) { if (!type && widgetXML) { // in widgetXML mode, if the tag name matches any known complexType, treat this as // a type override. Allows eg <ListGrid> to override the "members" field type being // "Canvas" var tagName = element.tagName; if (tagName == this._$List || isc.DS.get(tagName)) type = element.tagName; } // handle like field.multiple=true if List type explicitly specified if (type != null && type == this._$List) { var children = this.getElementChildren(element); return this.toJS(children, attrMask, dataSource, widgetXML, context); } // otherwise if explicit type is set, honor it if (type) { if (isc.DS.get(type) != null) { // NOTE: this case currently occurs only for widgetXML mode and schemaless // mode, otherwise, you don't get into this block dataSource = isc.DS.get(type); } else { // simple type return isc.SimpleType.validateValue(type, this.getElementText(element)); } } } // respect custom xmlToJS transform if (dataSource && dataSource.xmlToJS) return dataSource.xmlToJS(element, context); if (this.elementIsNil(element)) return null; // if a dataSource was passed, ask the DataSource to derive the field values for any field // that defines a valueXPath or getFieldValue function if (dataSource) { fieldNames = attrMask || dataSource.getFieldNames(); object = {}; for (var i = 0; i < fieldNames.length; i++) { var fieldName = fieldNames[i], field = dataSource.getField(fieldName); if (field == null || (field.valueXPath == null && field.getFieldValue == null)) continue; var value = dataSource.getFieldValue(element, fieldName, field); if (value != null) { if (this.logIsDebugEnabled(this._$xmlToJS)) { this.logDebug("valueXPath / getFieldValue() field: " + dataSource.ID + "." + fieldName + " on element: " + this.echoLeaf(element) + " got value: " + value, "xmlToJS"); } object[fieldName] = value; } } //this.logWarn("object is now: " + this.echo(object)); } // get attributes (or if a dataSource was passed, add to existing object without // clobbering) object = this.getAttributes(element, attrMask, object, dataSource != null, dataSource); // no attributes, no element children: convert to simple value if (!this._hasDataAttributes(object) && !this.hasElementChildren(element)) { return this.getElementText(element); } if (object[this._$xsiType] && object[this._$xsiType] == "xsd:Object") { delete object[this._$xsiType]; } // tranform subelements to properties var children = element.childNodes; var hadElementChildren = false; for (var i = 0; i < children.length; i++) { var child = children[i]; // we want the non-namespaced name var childName = this.getLocalName(child); // skip text nodes, which in FF we get every time the source XML has CRs if (this.isTextNode(child)) continue; hadElementChildren = true; // if we have an attrMask, ignore child elements not listed in the attrMask if (attrMask && !attrMask.contains(childName)) continue; var field = dataSource ? dataSource.getField(childName) : null; // if there was a field defined with this name that had a valueXPath or getFieldValue // function, ignore the subelement if (field && (field.valueXPath || field.getFieldValue)) continue; var childValue; if (this.logIsInfoEnabled(this._$xmlToJS)) { this.logInfo("dataSource: " + dataSource + ", field: " + this.echoLeaf(field) + (field != null ? " type: " + field.type : "") + ", XML element: " + this.echoLeaf(child), "xmlToJS"); } // field.multiple means the immediate child is just a container tag indicating // the property name - the indirect children are the elements that actually // conform to the declared type and provide the value var fieldValue = child; if (field && field.multiple) { // use the indirectChildren as the value, unless they're aren't any var indirectChildren = this.getElementChildren(child); if (indirectChildren.length > 0) fieldValue = indirectChildren; } if (!dataSource || field == null || field.type == null) { if (this.logIsDebugEnabled(this._$xmlToJS)) { this.logDebug("applying schemaless transform at: " + (dataSource ? dataSource.ID : "[schemaless]") + "." + childName, "xmlToJS"); } // if we have no source of type, perform recursive schemaless transform. // Note we'll do this even if we have a field, but the field is typeless (the field // may, eg, specify multiple:true) childValue = this.toJS(fieldValue, null, null, widgetXML, context); } else { var childSchema = dataSource.getSchema(field.type); // if the field is of dataSource type, do recursive transform if (childSchema != null) { var childContext = field.propertiesOnly ? {propertiesOnly: true} : context; childValue = this.toJS(fieldValue, null, childSchema, widgetXML, childContext); if (this.logIsDebugEnabled(this._$xmlToJS)) { this.logDebug("complexType field: " + this.echoLeaf(field) + " got value: " + this.echoLeaf(childValue), "xmlToJS"); } // otherwise, get the simple value } else { // NOTE: there's no way to use eg xsi:type to override an explicitly declared // simple type on a field (no known use case for this however) // field is multiple:true if (isc.isAn.Array(fieldValue)) { childValue = []; for (var j = 0; j < fieldValue.length; j++) { childValue.add( dataSource.validateFieldValue(field, this.getElementText(fieldValue[j])) ); } } else { childValue = dataSource.validateFieldValue(field, this.getElementText(fieldValue));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -