Created
December 26, 2014 21:48
-
-
Save brettz9/53aa246b4992846b5d1a to your computer and use it in GitHub Desktop.
XSLT in XHTML; allows self-contained XSLT 1.0 to be run from an XHTML page (without user JavaScript); currently works Firefox only (might work in IE with XSLTProcessor polyfill; other browsers had unknown problems transforming the XSLT)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*global XSLTProcessor, DOMParser, XMLSerializer*/ | |
/*jslint vars:true */ | |
/*! https://mths.be/array-from v0.2.0 by @mathias */ | |
if (!Array.from) { | |
(function() { | |
'use strict'; | |
var defineProperty = (function() { | |
var result; | |
// IE 8 only supports `Object.defineProperty` on DOM elements. | |
try { | |
var object = {}; | |
var $defineProperty = Object.defineProperty; | |
result = $defineProperty(object, object, object) && $defineProperty; | |
} catch(ignore) {} | |
return result || function put(object, key, descriptor) { | |
object[key] = descriptor.value; | |
}; | |
}()); | |
var toStr = Object.prototype.toString; | |
var isCallable = function(fn) { | |
// In a perfect world, the `typeof` check would be sufficient. However, | |
// in Chrome 1–12, `typeof /x/ == 'object'`, and in IE 6–8 | |
// `typeof alert == 'object'` and similar for other host objects. | |
return typeof fn === 'function' || toStr.call(fn) === '[object Function]'; | |
}; | |
var toInteger = function(value) { | |
var number = Number(value); | |
if (isNaN(number)) { | |
return 0; | |
} | |
if (number === 0 || !isFinite(number)) { | |
return number; | |
} | |
return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number)); | |
}; | |
var maxSafeInteger = Math.pow(2, 53) - 1; | |
var toLength = function(value) { | |
var len = toInteger(value); | |
return Math.min(Math.max(len, 0), maxSafeInteger); | |
}; | |
var from = function(arrayLike) { | |
var C = this; | |
if (arrayLike === null || arrayLike === undefined) { | |
throw new TypeError('`Array.from` requires an array-like object, not `null` or `undefined`'); | |
} | |
var items = Object(arrayLike); | |
var mapFn, T; | |
if (arguments.length > 1) { | |
mapFn = arguments[1]; | |
if (!isCallable(mapFn)) { | |
throw new TypeError('When provided, the second argument to `Array.from` must be a function'); | |
} | |
if (arguments.length > 2) { | |
T = arguments[2]; | |
} | |
} | |
var len = toLength(items.length); | |
var A = isCallable(C) ? Object(new C(len)) : new Array(len); | |
var k = 0; | |
var kValue, mappedValue; | |
while (k < len) { | |
kValue = items[k]; | |
if (mapFn) { | |
mappedValue = T === undefined ? mapFn(kValue, k) : mapFn.call(T, kValue, k); | |
} else { | |
mappedValue = kValue; | |
} | |
defineProperty(A, k, { | |
'value': mappedValue, | |
'configurable': true, | |
'enumerable': true | |
}); | |
++k; | |
} | |
A.length = len; | |
return A; | |
}; | |
defineProperty(Array, 'from', { | |
'value': from, | |
'configurable': true, | |
'writable': true | |
}); | |
}()); | |
} | |
window.addEventListener('DOMContentLoaded', function () {'use strict'; | |
// The following is ok for text/html, but not application/xhtml+xml (but text/html has issues with fragments of table rows not getting added properly, etc., so it can't be used for WYSIWYG templating) | |
// var stylesheets = Array.from(document.querySelectorAll('xsl\\:stylesheet')).concat(Array.from(document.querySelectorAll('xsl\\:transform'))); | |
var stylesheets = Array.from(document.querySelectorAll('stylesheet')).concat(Array.from(document.querySelectorAll('transform'))); | |
stylesheets.forEach(function (stylesheet) { | |
var processor = new XSLTProcessor(); | |
var doc = new DOMParser().parseFromString(new XMLSerializer().serializeToString(stylesheet), 'application/xml'); | |
processor.importStylesheet(doc); | |
var frag = processor.transformToFragment(document.createElement('dummy'), document); | |
stylesheet.parentNode.replaceChild(frag, stylesheet); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html xmlns="http://www.w3.org/1999/xhtml"> | |
<meta charset="utf-8" /> | |
<script src="xsl-in-xhtml.js"></script> | |
<xsl:stylesheet version="1.0" | |
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> | |
<xsl:variable name="header"> | |
<tr> | |
<th>Relationship</th> | |
<th>Name 1</th> | |
<th>Name 2</th> | |
</tr> | |
</xsl:variable> | |
<xsl:variable name="family"> | |
<parent>Brett</parent> | |
<parent>Coco</parent> | |
<child>Alex</child> | |
<child>Mia</child> | |
</xsl:variable> | |
<xsl:variable name="familyNode" select="document('')//*[local-name() = 'variable' and @name = 'family']"/> | |
<xsl:variable name="parent" select="$familyNode/*[local-name() = 'parent']"/> | |
<xsl:variable name="child" select="$familyNode/*[local-name() = 'child']"/> | |
<xsl:template match="/"> | |
<html> | |
<body> | |
<table border="1"> | |
<xsl:copy-of select="$header"/> | |
<tr> | |
<td><xsl:value-of select="name($parent)"/></td> | |
<xsl:for-each select="$parent"> | |
<td><xsl:copy-of select="."/></td> | |
</xsl:for-each> | |
</tr> | |
<tr> | |
<td><xsl:value-of select="name($child)"/></td> | |
<xsl:for-each select="$child"> | |
<td><xsl:copy-of select="."/></td> | |
</xsl:for-each> | |
</tr> | |
</table> | |
</body> | |
</html> | |
</xsl:template> | |
</xsl:stylesheet> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment