During investigation of advantages and disadvantages of attaching CSS with <?xml-stylesheet> processing instruction, I came upon some issues.
Suppose we have a simple XHTML document (which is delivered with application/xhtml+xml MIME type and viewed in a Web browser):
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>A sample XHTML document</title>
<script type="application/javascript" src="/script.js"></script>
</head>
<body>
<h1>A heading</h1>
</body>
</html>
Then we have an external CSS file (let it be named style.css and put in root directory):
h1 { color: red; }
At first, in script.js, I dynamically attach this CSS with a link element:
const link = document.createElement('link');
Object.entries({rel: 'stylesheet', type: 'text/css', href: '/style.css'})
.forEach(([name, value]) => link.setAttribute(name, value));
document.head.appendChild(link);
Then the script is waiting until the stylesheet finishes loading and reaches it through sheet property:
link.addEventListener('load', function() {
const stylesheet = link.sheet;
});
After this, the script can manipulate this stylesheet, for example:
stylesheet.cssRules.item(0).style.color = 'green'; // modify an existing rule
stylesheet.insertRule('body { background: #ffc; }', 1); // insert a new rule
But now, I cannot figure out whether the same manipulations are possible if a stylesheet is attached with <?xml-stylesheet> processing instruction:
const pi = document.createProcessingInstruction('xml-stylesheet',
'href="/style.css" type="text/css"');
document.insertBefore(pi, document.documentElement);
First, PI seem not to have load event, so the script cannot know when the stylesheet is ready. Second, there is nothing like sheet property, so you cannot call pi.sheet to reach the stylesheet.
Is there any way to overcome these difficulties and to get from the script to the stylesheet associated with <?xml-stylesheet> PI?
You can use
PerformanceObserverto check for requested and loaded resources. Iterates nodes ofdocument, check for.nodeType7or.nodeType8, asProcessingInstructionnode could havecomment.nodeType. Get"resource"property from performance entries. Parse.nodeValueof filtered node for URL athref="URL", check if value is equal to"resource"of performance entry, then check if.styleSheet.hrefvalue is equal to parsed URL, and if parsed URL is equal to performance entry"resource"property value. Iftrue, iterate.cssRulesor.rulesof thestyleSheetloaded atProcessingInstructionnode.plnkr http://plnkr.co/edit/uXfSzu0dMDCOfZbsdA7n?p=preview
You can also use
MutationObserver,setTimeout()to handleplnkr http://plnkr.co/edit/AI4QZiBUx6f1Kmc5qNG9?p=preview
Alternatively, use
XMLHttpRequest()orfetch()to request.cssfile, create and append<style>element todocument, do stuff with response text, set.textContentofstyleelement to adjustedcsstext.