Open GoogleCodeExporter opened 9 years ago
Cool. Please post the unidiff of your change as a comment to this change, so
it's
easier to see what it's about. Consider to split them up into separate changes,
so
it's more obvious what they do. Thanks!
Original comment by me...@google.com
on 21 May 2007 at 9:59
Hmm. Did some unidiff's and notice a bug and also that I left out my changes to
xslt.js in that zip. Anyway, here's the changes to utils.js first:
6a7,69
> // URI functions. Regular expression adapted from that in RFC 2396.
> // (resolvePartialUri works for all of the examples given in that RFC, though
> // the alternative interpretation of ../../../g will be produced (not for the
> // reason suggested in that RFC - it's just the way it worked :)
> function parseUri(uri)
> {
> return
/^(([^:/?#]+):)?([/]{2}([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/.exec(uri);
> }
> function isRelativeUri(uri)
> {
> return parseUri(uri)[1] == undefined;
> }
> function resolvePartialUri(base, partial)
> {
> var arr = parseUri(partial);
> if(arr[1] != undefined)//Uri is full.
> return partial;
> arrBase = parseUri(base);
> if(arr[3] != undefined)
> return arrBase[1] + partial;
> if(arr[5] != undefined && arr[5].substring(0, 1) == '/')//abspath
> return arrBase[1] + arrBase[3] + partial;
> if(arr[5] != undefined && arr[5].length)
> {
> var steps = arr[5].split('/')
> var stepsBase = arrBase[5].split('/');
> stepsBase.length--;
> for(var i = 0; i < steps.length; ++i)
> switch(steps[i])
> {
> case '.':
> steps.splice(i--, 1);
> break;
> case '..':
> steps.splice(i--, 1);
> if(i > -1)
> {
> steps.splice(0, 1);
> --i;
> }
> else if(stepsBase.length)
> stepsBase.length--;
> break;
> }
> return arrBase[1] + arrBase[3] + stepsBase.join('/') + '/' +
steps.join('/') +
(arr[6] == undefined ? '' : arr[6]) + (arr[8] == undefined ? '' : arr[8]);
> }
> if(arr[6] != undefined)
> return arrBase[1] + arrBase[3] + arrBase[5].substring(0,
arrBase[5].lastIndexOf('/') + 1) + arr[6] + (arr[8] == undefined ? '' : arr[8]);
> if(arr[8] != undefined)
> return arrBase[1] + arrBase[3] + arrBase[5] + (arrBase[6] == undefined ? ''
:
arrBase[6]) + arr[8];
> return arrBase[1] + arrBase[3] + arrBase[5] + (arrBase[6] == undefined ? '' :
arrBase[6]);
> }
> // Wraps around alert() so that we need not assume that these scripts are
being
> // used in a context that offers alert() - i.e. a browser.
> // Also allows for termination by throwing an error.
> function reportMessage(msg, terminate)
> {
> alert(msg);
> //xpathLog((terminate ? 'Terminating Message: ' : 'Message: ') + msg);
> if(terminate)
> throw 'Terminating Message: ' + msg;
> }
>
403a467,470
> function domCreateProcessingInstruction(doc, target, data) {//need to test
level of
support
> return doc.createProcessingInstruction(target, data);
> }
>
Original comment by j...@hackcraft.net
on 21 May 2007 at 11:01
Now dom.js:
74a75,148
> //Returns true if an HTMLRequest object can be created.
> //Hence indicates if there is a chance of xmlLoad working
> //and hence that document() in XSLT can work.
> //Written by Jon Hanna <jon@hackcraft.net>.
> function xmlLoadAvailable()
> {
> if (window.XMLHttpRequest) // Mozilla, Safari, Firefox...
> {
> return true;
> }
> else if (window.ActiveXObject)// IE
> {
> try
> {
> var test_request = new ActiveXObject("Msxml2.XMLHTTP");
> return true;
> }
> catch (e)
> {
> try
> {
> var test_request = new ActiveXObject("Microsoft.XMLHTTP");
> return true;
> }
> catch (e) {return false}
> }
> }
> else
> return false;
> }
> //Loads an XDocument from a URI.
> //Scheme support is browser-dependent, though all support HTTP at a minimum.
> //Written by Jon Hanna <jon@hackcraft.net>.
> //Amongst other things lets document() work (should we just use the DOM object
> //from XMLHttpRequest::responseXML on some browsers?)
> function xmlLoad(uri)
> {
> var http_request;
> if (window.XMLHttpRequest) // Mozilla, Safari, Firefox...
> {
> http_request = new XMLHttpRequest();
> if (http_request.overrideMimeType)
> {
> http_request.overrideMimeType('text/xml');
> }
> }
> else if (window.ActiveXObject)// IE
> {
> try
> {
> http_request = new ActiveXObject("Msxml2.XMLHTTP");
> }
> catch (e)
> {
> try
> {
> http_request = new ActiveXObject("Microsoft.XMLHTTP");
> }
> catch (e) {return null;}
> }
> }
> else
> return null;
>
> try
> {
> http_request.open('GET', uri, false);
> }
> catch(e){}
> http_request.send(null);
> var doc = xmlParse(http_request.responseText);
> doc.baseUri = uri;
> return doc;
> }
323a398,412
> //Base URI see http://www.w3.org/TR/xmlbase/
> //Find the nearest ancestor with an xml:base attribute. If absolute, that's
the base
> //if relative it's relative to the next xml:base attribute. If we crawl as
far as the
> //root then the base there is the URI it was loaded from (why this is defined
differently
> //on XDocument).
> XNode.prototype.getBaseUri = function()
> {
> var decHere = this.getAttribute('xml:base');
> if(decHere == null)
> return this.parentNode ? this.parentNode.getBaseUri() : null;
> if(isRelativeUri(decHere) && this.parentNode)
> return resolvePartialUri(this.parentNode.getBaseUri(), decHere);
> return decHere;
> }
>
519a609
> this.baseUri = '';
527a618,621
> XDocument.prototype.getBaseUri = function()
> {
> return this.baseUri;
> }
Now xslt.js:
66c66
< alert('not implemented: ' + nodename[1]);
---
> reportMessage('not implemented: ' + nodename[1], true);
111c111
< alert('not implemented: ' + nodename[1]);
---
> reportMessage('not implemented: ' + nodename[1], true);
167c167
< alert('not implemented: ' + nodename[1]);
---
> reportMessage('not implemented: ' + nodename[1], true);
179c179
< alert('not implemented: ' + nodename[1]);
---
> reportMessage('not implemented: ' + nodename[1], true);
194c194
< alert('not implemented: ' + nodename[1]);
---
> reportMessage('not implemented: ' + nodename[1], true);
198c198
< alert('not implemented: ' + nodename[1]);
---
> reportMessage('not implemented: ' + nodename[1], true);
202c202
< alert('not implemented: ' + nodename[1]);
---
> reportMessage('not implemented: ' + nodename[1], true);
206,207c206,211
< alert('not implemented: ' + nodename[1]);
< break;
---
> var msgOutput = domCreateDocumentFragment(new XDocument)
> var msgOutputDocument = xmlOwnerDocument(output);
> xsltChildNodes(input, template, msgOutput);
> alert(msgOutput.toSource())
> reportMessage(xmlValue(msgOutput), xmlGetAttribute(template,
'terminate') ==
'yes')
> break;
210c214
< alert('not implemented: ' + nodename[1]);
---
> reportMessage('not implemented: ' + nodename[1], true);
214c218
< alert('not implemented: ' + nodename[1]);
---
> reportMessage('not implemented: ' + nodename[1], true);
218c222
< alert('error if here: ' + nodename[1]);
---
> reportMessage('error if here: ' + nodename[1], true);
229c233
< alert('not implemented: ' + nodename[1]);
---
> reportMessage('not implemented: ' + nodename[1], true);
233c237
< alert('not implemented: ' + nodename[1]);
---
> reportMessage('not implemented: ' + nodename[1], true);
241c245
< alert('not implemented: ' + nodename[1]);
---
> reportMessage('not implemented: ' + nodename[1], true);
278c282
< alert('error if here: ' + nodename[1]);
---
> reportMessage('error if here: ' + nodename[1], true);
282c286
< alert('error if here: ' + nodename[1]);
---
> reportMessage('error if here: ' + nodename[1], true);
286c290
< alert('error if here: ' + nodename[1]);
---
> reportMessage('error if here: ' + nodename[1], true);
And here's the big one, xpath.js:
44c44
< xpathLog('parse ' + expr);
---
> //xpathLog('parse ' + expr);
49c49
< xpathLog(' ... cached');
---
> //xpathLog(' ... cached');
62c62
< xpathLog(' ... simple');
---
> //xpathLog(' ... simple');
69c69
< xpathLog(' ... simple 2');
---
> //xpathLog(' ... simple 2');
132c132
< xpathLog('token: ' + match + ' -- ' + rule.label);
---
> //xpathLog('token: ' + match + ' -- ' + rule.label);
141c141
< xpathLog('DONE');
---
> //xpathLog('DONE');
147c147
< xpathLog('stack: ' + stackToString(stack));
---
> //xpathLog('stack: ' + stackToString(stack));
151c151
< xpathLog('stack: ' + stackToString(stack));
---
> //xpathLog('stack: ' + stackToString(stack));
160,161c160
< xpathLog('XPath parse: ' + parse_count + ' / ' +
< lexer_count + ' / ' + reduce_count);
---
> //xpathLog('XPath parse: ' + parse_count + ' / ' + lexer_count + ' / ' +
reduce_count);
203,206c202
< xpathLog('reduce ' + cand.tag.label + ' ' + cand.prec +
< ' ahead ' + (ahead ? ahead.tag.label + ' ' + ahead.prec +
< (ahead.tag.left ? ' left' : '')
< : ' none '));
---
> //xpathLog('reduce ' + cand.tag.label + ' ' + cand.prec + ' ahead ' +
(ahead ?
ahead.tag.label + ' ' + ahead.prec + (ahead.tag.left ? ' left' : '') : ' none
'));
216,219c212
< xpathLog('shift ' + ahead.tag.label + ' ' + ahead.prec +
< (ahead.tag.left ? ' left' : '') +
< ' over ' + (cand ? cand.tag.label + ' ' +
< cand.prec : ' none'));
---
> //xpathLog('shift ' + ahead.tag.label + ' ' + ahead.prec +
(ahead.tag.left ?
' left' : '') + ' over ' + (cand ? cand.tag.label + ' ' + cand.prec : ' none'));
673c666
< alert('not implemented: axis namespace');
---
> reportMessage('not implemented: axis namespace', true);
813c806
< xpathLog('XPath NO SUCH FUNCTION ' + fn);
---
> //xpathLog('XPath NO SUCH FUNCTION ' + fn);
865c858,862
< alert('not implmented yet: XPath function local-name()');
---
> //Let name() do most of the work!
> assert(this.args.length == 1 || this.args.length == 0);
> var name = this.xpathfunctions['name'].call(this, ctx).stringValue();
> var idx = name.indexOf(':');
> return new StringValue(idx == -1 ? name : name.substring(idx + 1,
name.length));
868,869c865,879
< 'namespace-uri': function(ctx) {
< alert('not implmented yet: XPath function namespace-uri()');
---
> 'namespace-uri': function(ctx) {//TODO. This depends upon the namespace
handling
being "TODO" in XNode and XDocument objects. Must fix this function once those
have
full namespace support.
> var name = this.xpathfunctions['name'].call(this, ctx).stringValue();
> var idx = name.indexOf(':');
> var nsAtt = idx == -1 ? 'xmlns' : 'xmlns:' + name.substring(0, idx);
>
> var xmlns;
> var n = ctx.node;
> while (n && n != n.parentNode /* just in case ... */) {
> xmlns = n.getAttribute(nsAtt);
> if (xmlns) {
> break;
> }
> n = n.parentNode;
> }
> return new StringValue(xmlns ? xmlns : '');
898,899c908,910
< var ret = '';
< for (var i = 0; i < this.args.length; ++i) {
---
> assert(this.args.length > 1);
> var ret = this.args[0].evaluate(ctx).stringValue(); //<jon@hackcraft.net>:
minor efficiency gain.
> for (var i = 1; i < this.args.length; ++i) {
996c1007,1009
< s0 = s0.replace(new RegExp(s1.charAt(i), 'g'), s2.charAt(i));
---
> if(s1.indexOf(s1.charAt(i)) == i) {//repeated characters in s1 should
NOT be
used.
> s0 = s0.replace(new RegExp(s1.charAt(i), 'g'), s2.charAt(i));
> }
1124c1137,1290
< }
---
> },
> // Following functions are the extensions to
> // XPath added by XSLT. <jon@hackcraft.net>
> 'current': function(ctx){
> assert(this.args.length == 0);
> var ret = [];
> ret.push(_current_node);
> return new NodeSetValue(ret);
> },
> 'document': function(ctx){
> assert(this.args.length == 1 || this.args.length == 2);
> var nodes = this.args.length > 1 ?
this.args[0].evaluate(ctx).nodeSetValue() :
null;
> var baseUriNode = nodes && nodes.length ? nodes[0] : null; //TODO: Make
it use
first node in *document order*.
> var baseUri = baseUriNode ? baseUriNode.getBaseUri() : null;
>
> var firstArg = this.args[0].evaluate(ctx);
> var uris = []
> if(firstArg.type == 'node-set')
> {
> var nodeSet = firstArg.nodeSetValue()
> for(var i = 0; i != nodeSet.length; ++i)
> if(baseUri)
> uris.push(resolvePartialUri(baseUri, xmlValue(nodeSet[i])));
> else
> uris.push(resolvePartialUri(nodeSet[i].getBaseUri(),
xmlValue(nodeSet[i])));
> }
> else
> {
> if(baseUri)
> uris.push(resolvePartialUri(baseUri, firstArg.stringValue()));
> else
> uris.push(firstArg.stringValue());
> }
> var ret = [];
> for(var i = 0; i != uris.length; ++i)
> {
> var newDom = xmlLoad(uris[i]);
> ret.push(newDom);
> }
> return new NodeSetValue(ret);
> },
> 'element-available': function(ctx){
> assert(this.args.length == 1);
> var elName = this.args[0].evaluate(ctx).stringValue();
> if(elName.indexOf('xslt:') == 0)//fake support for commonly used xslt
namespace
prefix
> elName = elName.substring(5, elName.length);
> else if(elName.indexOf('xsl:') == 0)//fake support for commonly used xslt
namespace prefix
> elName = elName.substring(4, elName.length);
>
> if(elName.indexOf(':') != -1)//Non-XSLT element - none supported.
> return new BooleanValue(false);
> switch(elName)
> {
> case 'apply-templates':
> case 'attribute':
> case 'call-template':
> case 'choose':
> case 'comment':
> case 'copy':
> case 'copy-of':
> case 'element':
> case 'for-each':
> case 'if':
> case 'message':
> case 'otherwise':
> case 'output':
> case 'sort':
> case 'stylesheet':
> case 'transform':
> case 'template':
> case 'text':
> case 'value-of':
> case 'param':
> case 'variable':
> case 'when':
> case 'with-param':
> return new BooleanValue(true);
> default:
> return new BooleanValue(false);
> }
> },
> 'format-number': function(ctx){
> reportMessage('not implmented yet: XSLT extension XPath function
format-number()', true);
> },
> 'function-available': function(ctx){
> assert(this.args.length == 1);
> var funcName = this.args[0].evaluate(ctx).stringValue();
> if(funcName.indexOf(':') != -1)//Non-XSLT extended function - none
supported.
> return new BooleanValue(false);
> if(!FunctionCallExpr.prototype.xpathfunctions[funcName])//Not defined
here at all.
> return new BooleanValue(false);
> switch(funcName)
> {
> case 'format-number':
> case 'key':
> case 'unparsed-entity-uri':
> return new BooleanValue(false);
> case 'document':
> return new BooleanValue(xmlLoadAvailable());
> default:
> return new BooleanValue(true);
> }
>
> },
> 'generate-id': function(ctx){
> //The spec insists that we guarantee a consisten id such that if
generate-id
> //is called on the same node twice we return the same id, but we would
never
> //return the same id for two different ones. This method is far from
efficient
> //nor concise in the ids generated, but it is simple and fulfils the spec.
> assert(this.args.length == 1 || this.args.length == 0);
> var n;
> if (this.args.length == 0) {
> n = ctx.node;
> } else {
> n = this.args[0].evaluate(ctx).nodeSetValue()[0];
> }
> var genId = '';
> while (n && n != n.parentNode /* just in case ... */) {
> var c = 0;
> var p = n.previousSibling;
> while(p)
> {
> ++c;
> p = p.previousSibling;
> }
> genId = '_' + c + genId;
> n = n.parentNode;
> }
> return new StringValue(genId);
> },
> 'key': function(ctx){
> reportMessage('not implmented yet: XSLT extension XPath function key()',
true);
> },
> 'system-property': function(ctx){
> assert(this.args.length == 1);
> var propName = this.args[0].evaluate(ctx).stringValue();
> var idx = propName.indexOf(':');
> if(idx != -1)//TODO: Fix namespace check. Until then, assume everything
is in
the XSLT namespace and take local part:
> propName = propName.substring(idx + 1, propName.length);
> switch(propName)
> {
> case 'version':
> return new StringValue('1.0');
> case 'vendor':
> return new StringValue('Google Code');
> case 'vendor-url':
> return new StringValue('http://code.google.com/');
> default:
> return new StringValue('');
> }
> },
> 'unparsed-entity-uri': function(ctx){
> reportMessage('not implmented yet: XSLT extension XPath function
unparsed-entity-uri()', true);
> },
1267c1433
< alert('BinaryExpr.evaluate: ' + this.op.value);
---
> reportMessage('BinaryExpr.evaluate: ' + this.op.value, true);
1640c1806
< var xpathAxesRe = [
---
> var xpathAxesRe = '(' + [
1654c1820
< ].join('|');
---
> ].join('|') + ')(?=::)';
1927c2093
< [ XPathFilterExpr, [ XPathPrimaryExpr, XPathPredicate, Q_MM ], 20,
---
> [ XPathFilterExpr, [ XPathPrimaryExpr, XPathPredicate, Q_MM ], 31,
2017c2183
< xpathLog('XPath parse INIT: ' + k + ' rules');
---
> //xpathLog('XPath parse INIT: ' + k + ' rules');
2055c2221
< xpathLog('XPath parse INIT: ' + xpathRules.length + ' rule bins');
---
> //xpathLog('XPath parse INIT: ' + xpathRules.length + ' rule bins');
2064,2065c2230
< xpathLog('XPath parse INIT: ' + (sum / xpathRules.length) +
< ' average bin size');
---
> //xpathLog('XPath parse INIT: ' + (sum / xpathRules.length) + ' average bin
size');
2162c2327
<
---
> var _current_node;//<jon@hackcraft.net>: Used for current(). TODO - this is
global
and will have problems if two transforms are simultaneous
2165a2331
> _current_node = context.node;//<jon@hackcraft.net>: Used for current().
Original comment by j...@hackcraft.net
on 21 May 2007 at 11:03
Gosh, did more than I'd realised :).
The change:
1640c1806
< var xpathAxesRe = [
---
> var xpathAxesRe = '(' + [
1654c1820
< ].join('|');
---
> ].join('|') + ')(?=::)';
is because otherwise the parsing matched 'namespace' in 'namespace-uri()' and
interpretted that as identifying the namespace axis. The above change means
that axes
have to be followed by :: to match.
The line:
> var msgOutputDocument = xmlOwnerDocument(output);
Can be dropped - it's just from what I was thinking about at the time!
Original comment by j...@hackcraft.net
on 21 May 2007 at 11:28
Any chance of a new version release incorporating this patch?
Original comment by albert.l...@gmail.com
on 28 Sep 2007 at 12:16
This patch is huge, and hard to make sense of. It would be a lot of work to
apply
this patch correctly; I doubt we'll want to apply it as-is. (Especially since
it
introduces several TODOs and includes no tests.)
A few comments:
1) We need to provide more complete support for namespace resolution; this patch
gestures in that direction, but doesn't go all the way, and I think we'd need
to cut
out the changes submitted here if/when we ever did implement namespace
resolution.
2) The implementation of document() relies on XmlHttpRequest, which is puzzling,
because if you've got XHR, you probably have XSLT support built-in.
3) The use of a global variable to handle current() is concerning.
If somebody can call out one part of the patch that they need in the release
(perhaps
filing a separate bug?) we can talk about implementing these features (perhaps
using
part of this patch?) on a one-off basis.
Original comment by DanFabul...@gmail.com
on 7 Nov 2007 at 4:56
"2) The implementation of document() relies on XmlHttpRequest, which is
puzzling,
because if you've got XHR, you probably have XSLT support built-in."
Safari and Google Chrome have XmlHttpRequest but don't process the document
function
using the built in XSLTProcessor object, perhaps you could rethink including at
least
this part of this patch?
Original comment by neerol...@gmail.com
on 11 Sep 2008 at 4:16
Original issue reported on code.google.com by
j...@hackcraft.net
on 21 May 2007 at 5:20Attachments: