📄 xmltools.js
字号:
// <P>// <b>NOTE:</b> this API cannot be supported on the Safari web browser for versions earlier// than 3.0.3.//// @param element (XMLElement or XMLDocument) Native XMLElement or document to select from// @param expression (XPath) XPath expression to use to select nodes// @param [namespaces] (prefix -> URI mapping) namespace mapping used by the expression// @return (Array) list of nodes matching XPath//// @group xmlTransform// @visibility xmlBinding// @example xmlServerValidationErrors//<selectNodes : function (element, expression, namespaces, single) { if (isc.Browser.isSafari && (isc.Browser.isApollo || (isc.Browser.safariVersion < 522))) { this._warnIfNativeXMLUnavailable("XPath"); return this.safariSelectNodes(element, expression, namespaces, single); } if (isc.isAn.XMLDoc(element)) { return element.selectNodes(expression, namespaces, single); } var start = isc.timestamp(); var returnValue = this._selectNodes(element, expression, namespaces, single); var end = isc.timestamp(); if (this.logIsInfoEnabled("xmlSelect")) { this.logInfo("selectNodes: expression: " + expression + " returned " + this.echoLeaf(returnValue) + ": " + (end-start) + "ms", "xmlSelect"); } return returnValue;},// Do very crude emulation of XPath for older Safari and older WebKit (like Adobe AIR)// where native XPath is not available.safariSelectNodes : function (element, expression, namespaces, single) { var elements = []; if (!expression) { return null; } var recordName = expression.substring(expression.indexOf(":")+1); var pickUpSubElements; if (recordName.endsWith("/*")) { pickUpSubElements = true; recordName = recordName.substring(0, recordName.indexOf("/*")); } // NOTE: a tagName of "record" matches <foo:record> in Moz, but NOT in IE var nodeList = element.getElementsByTagName(recordName); if (pickUpSubElements && nodeList.length > 0) { var parent = nodeList[0]; nodeList = parent.childNodes; } for (var i = 0; i < nodeList.length; i++) { // don't pick up text nodes -- can happen when iterating through childNode array // to simulate /* xpath if (nodeList[i].nodeType == 3) continue; elements.add(nodeList[i]); } // don't create a spurious Array for the most common case of a singular body // element if (pickUpSubElements && elements.length == 1) elements = elements[0]; return elements;}, // namespaces: map from prefix -> namespaceURI// prefixes: option list of prefixes _generateNamespaces : function (namespaces, prefixes, indent) { if (namespaces == null) return isc.emptyString; if (prefixes == null) prefixes = isc.getKeys(namespaces); var buffer = isc.SB.create(), indent = (indent != null ? "\n" + indent : ""); for (var i = 0; i < prefixes.length; i++) { var prefix = prefixes[i]; buffer.append(indent, " xmlns:", prefix, '="', namespaces[prefix], '"'); } return buffer.toString();},// called for Moz and Safari only - return a namespace to use for the "default:" prefix in// XPath selection_getDefaultNamespace : function (docElement) { // check for a default namespace on the document element. Note this will get // the default namespace established by the document element, even if the // document element itself is in another namespace var docNS = docElement.lookupNamespaceURI(""); if (isc.Browser.isSafari && (docNS == null || docNS == "")) { docNS = docElement.getAttribute("xmlns"); } // fall back to the namespace of the document element, even if it's not a // default namespace if (docNS == null) docNS = docElement.namespaceURI; // fall back to non-namespaced elements if (docNS == null) docNS = ""; return docNS},_selectNodes : function (element, expression, namespaces, single) { var doc = element.ownerDocument; if (doc == null && element.documentElement) { // a document object was passed doc = element; element = doc.documentElement; } if (isc.Browser.isIE) { if (isc.Browser.version > 5.5) { doc.setProperty("SelectionLanguage", "XPath"); var nsString = this._makeIEDefaultNamespaces(doc, namespaces); if (namespaces) nsString += this._generateNamespaces(namespaces); if (this.logIsDebugEnabled("xmlSelect")) { this.logDebug("selectNodes: expression: " + expression + ", using namespaces: " + nsString, "xmlSelect"); } doc.setProperty("SelectionNamespaces", nsString); } // if "single" was passed, select a single node if (single) return element.selectSingleNode(expression); // otherwise return an Array of nodes var nodes = element.selectNodes(expression); // convert native NodeList object to a JavaScript Array return this._nodeListToArray(nodes); } var baseResolver = doc.createNSResolver(doc.documentElement), defaultNamespace = this._getDefaultNamespace(doc.documentElement); if (this.logIsDebugEnabled("xmlSelect")) { this.logDebug("Using namespaces: " + isc.echo(namespaces) + ", defaultNamespace: '" + defaultNamespace + "'", "xmlSelect"); } var resolver = function (prefix) { // supplied namespaces first if (namespaces && namespaces[prefix]) return namespaces[prefix]; if (prefix == "default") return defaultNamespace; return baseResolver.lookupNamespaceURI(prefix); }; // 0 is resultType = XPathResult.ANY_TYPE var results = doc.evaluate(expression, element, resolver, 0, null); // if "single" was passed, just return the first node if (single) return results.iterateNext(); // convert native nodeList object to JavaScript Array return this._nodeListToArray(results);},// convert a native NodeList object to a JavaScript Array.// NodeLists are returned by native selectNodes() in IE or document.evaluate(xpath) in other// browsers. xmlElement.childNodes is also a NodeList_nodeListToArray : function (nodeList) { var output = []; if (isc.Browser.isIE || nodeList.iterateNext == null) { for (var i = 0; i < nodeList.length; i++) { output.add(nodeList.item(i)); } } else { var resultNode; while (resultNode = nodeList.iterateNext()) { output.add(resultNode); } } return output;},getElementChildren : function (element) { var output = [], childNodes = element.childNodes; for (var i = 0; i < childNodes.length; i++) { var child = childNodes[i]; if (this.isTextNode(child)) continue; output.add(child); } return output;},//> @classMethod XMLTools.selectString() [A]// Retrieve a string value from an XML element or document based on an XPath expression.// <P>// If more than one node matches, only the first node's value will be returned.// <P>// Namespacing works as described under +link{XMLTools.selectNodes()}// <P>// <b>NOTE:</b> this API cannot be supported on the Safari web browser for versions prior to// 3.0.3.//// @param element (XMLElement or XMLDocument) Native XMLElement or document to select from// @param expression (XPath) XPath expression to use to select nodes// @param [namespaces] (prefix -> URI mapping) namespace mapping used by the expression//// @return (String) result of the XPath, in String form//// @group xmlTransform// @visibility xmlBinding// @example xmlServerValidationErrors//<selectString : function (element, expression, namespaces) { return this.selectScalar(element, expression, namespaces);},//> @classMethod XMLTools.selectNumber() [A]// Retrieve a numeric value from an XML element or document based on an XPath expression.// <P>// If more than one node matches, only the first node's value will be returned.// <P>// Namespacing works as described under +link{XMLTools.selectNodes()}// <P>// <b>NOTE:</b> this API cannot be supported on the Safari web browser for versions prior to// 3.0.3.//// @param element (XMLElement or XMLDocument) Native XMLElement or document to select from// @param expression (XPath) XPath expression to use to select nodes// @param [namespaces] (prefix -> URI mapping) namespace mapping used by the expression//// @return (Number) result of the XPath, in Number form//// @group xmlTransform// @visibility xmlBinding//<selectNumber : function (element, expression, namespaces) { return this.selectScalar(element, expression, namespaces, true);},selectScalar : function (element, expression, namespaces, asNumber) { if (isc.isAn.XMLDoc(element)) return element.selectScalar(expression, namespaces, asNumber); // NOTE: the XPath standard allows you to ask for a specific "resultType", eg String or // Number, instead of a NodeSet. Moz does implement this. However, for both // resultType:String and resultType:Number, Moz returns identical results for absence of an // element vs empty element, whereas we'd like to be able to return null vs "" for these // two cases respectively. // // In IE we can get a singular node from selectSingleNode(), and we grab the and parseInt. // // NOTE also: in Moz at least, if we don't ask for a scalar type, Moz will never return it // for XPathResult.ANY: single text node results and single attribute results still return // unordered_node_iterator by default, with crashing stringValue and numberValue accessors // pass "true" to ask for a single node var value; if(isc.Browser.isSafari && isc.Browser.isApollo || (isc.Browser.safariVersion < 522)) { var name=expression.substring(expression.indexOf(":")+1); value=element.getElementsByTagName(name)[0]; }else{ value=this.selectNodes(element,expression,namespaces,true); } if (value == null) return null; var text = this.getElementText(value); return asNumber ? parseInt(text) : text;},// performs xpath select and returns array of strings that are the values of selected nodes.//// expects result of xpath select to be a list of Attribute or Text nodes. Performs an in-place// replacement on the list with the node values and returns that.// XXX internal until this handles simple elements in addition to attributesselectScalarList : function (element, expression, namespaces) { if (isc.isAn.XMLDoc(element)) return element.selectScalarList(expression, namespaces); var values = this.selectNodes(element, expression, namespaces); // Thank god attributes and text elements share the 'nodeValue' attribute that has the data. for (var i = 0; i < values.length; i++) { values[i] = values[i].nodeValue; } return values;},// XSLT// ---------------------------------------------------------------------------------------//> @classMethod XMLTools.transformNodes()// Apply an XSLT Stylesheet to an XML Document.// <P>// This method cannot currently be supported on the Safari web browser versions prior to// 3.0.3.//// @param inputDocument (XMLDocument) XML document to apply the transform to// @param styleSheet (XMLDocument) XSLT stylesheet to use for transform// @return (String) stylesheet output//// @group xmlTransform// @visibility xmlBinding//<transformNodes : function (inputDocument, styleSheet) { if (isc.isAn.XMLDoc(inputDocument)) inputDocument = inputDocument.nativeDoc; if (isc.isAn.XMLDoc(styleSheet)) styleSheet = styleSheet.nativeDoc; if (isc.Browser.isIE) { return inputDocument.transformNode(styleSheet); } var processor = new XSLTProcessor(); processor.importStylesheet(styleSheet); if (isc.Browser.isMoz && this.mozAnchorBug && isc.Browser.geckoVersion < 20051107) { var ownerDocument = document.implementation.createDocument("", "test", null); var newFragment = processor.transformToFragment(inputDocument, ownerDocument); return new XMLSerializer().serializeToString(newFragment); } var outputDocument = processor.transformToDocument(inputDocument); return new XMLSerializer().serializeToString(outputDocument); // transformToFragment can produce something that is not a well-formed document, for // example, just a text node. However this doesn't really mean that Mozilla supports XSLT // to text, sinc
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -