本文介绍了处理<?xml-stylesheet>类似于< link rel =" stylesheet">?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在调查使用<?xml-stylesheet> 处理说明附加CSS的优点和缺点时,我遇到了一些问题。

During investigation of advantages and disadvantages of attaching CSS with <?xml-stylesheet> processing instruction, I came upon some issues.

假设我们有一个简单的XHTML文档(随 application / xhtml + xml MIME类型一起提供并在Web浏览器中查看):

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>

然后我们有一个外部CSS文件(让它命名为 style.css 并放入根目录):

Then we have an external CSS file (let it be named style.css and put in root directory):

h1 { color: red; }

首先,在 script.js ,我用链接动态附加这个CSS



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);

然后脚本等待样式表完成加载并通过表到达 property:

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

但是现在,我无法弄清楚是否可以进行相同的操作样式表附有<?xml-stylesheet> 处理说明:

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);

首先,PI似乎没有加载事件,因此脚本无法知道样式表何时准备就绪。其次,没有像属性,所以你不能调用 pi.sheet 来访问样式表。

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.

有没有办法克服这些困难,并从脚本到与<?xml-stylesheet> PI?

Is there any way to overcome these difficulties and to get from the script to the stylesheet associated with <?xml-stylesheet> PI?

推荐答案

你可以使用 PerformanceObserver 检查请求和加载的资源。迭代文档的节点,检查 .nodeType 7 .nodeType 8 ,因为 ProcessingInstruction 节点可能 comment .nodeType 。从性能条目中获取resource属性。在 href =URL中解析URL的已过滤节点的 .nodeValue ,检查值是否等于资源的性能输入,然后检查 .styleSheet .href value等于已解析的URL,如果已解析的URL等于性能条目resource属性值。如果 true ,则迭代 .cssRules .rules styleSheet ProcessingInstruction 节点加载。

You can use PerformanceObserver to check for requested and loaded resources. Iterates nodes of document, check for .nodeType 7 or .nodeType 8, as ProcessingInstruction node could have comment .nodeType. Get "resource" property from performance entries. Parse .nodeValue of filtered node for URL at href="URL", check if value is equal to "resource" of performance entry, then check if .styleSheet .href value is equal to parsed URL, and if parsed URL is equal to performance entry "resource" property value. If true, iterate .cssRules or .rules of the styleSheet loaded at ProcessingInstruction node.

window.onload = () => {
  let resource;
  const observer = new PerformanceObserver((list, obj) => {
    for (let entry of list.getEntries()) {
      for (let [key, prop] of Object.entries(entry.toJSON())) {
        if (key === "name") {
          resource = prop;
          var nodes = document.childNodes;
          _nodes: for (let node of nodes) {
            if (node.nodeType === 7 || node.nodeType === 8
            && node.nodeValue === pi.nodeValue) {
              let url = node.baseURI
                        + node.nodeValue.match(/[^href="][a-z0-9/.]+/i)[0];
              if (url === resource) {
                observer.disconnect();
                // use `setTimeout` here for
                // low RAM, busy CPU, many processes running
                let stylesheets = node.rootNode.styleSheets;
                for (let xmlstyle of stylesheets) {
                  if (xmlstyle.href === url && url === resource) {
                    let rules = (xmlstyle["cssRules"] || xmlstyle["rules"]);
                    for (let rule of rules) {
                      // do stuff
                      console.log(rule, rule.cssText, rule.style, xmlstyle);
                      break _nodes;
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  });

  observer.observe({
    entryTypes: ["resource"]
  });

  const pi = document.createProcessingInstruction('xml-stylesheet',
    'href="style.css" type="text/css"');
  document.insertBefore(pi, document.documentElement);

}

plnkr

您还可以使用 MutationObserver setTimeout()来处理



window.onload = function() {
  let observer = new MutationObserver(function(mutations) {
    console.log(mutations)
    for (let mutation of mutations) {
      for (let node of mutation.addedNodes) {
        if (node.nodeName === "xml-stylesheet") {
          let url = node.baseURI
                    + node.nodeValue.match(/[^href="][a-z0-9/.]+/i)[0];
          setTimeout(function() {
            for (let style of document.styleSheets) {
              if (style.href === url) {
                observer.disconnect();
                // do stuff
                console.log(style)
              }
            }
          // adjust `duration` to compensate for device
          // low RAM, busy CPU, many processes running
          }, 500)
        }
      }
    }
  });

  observer.observe(document, {
    childList: true
  });

  const pi = document.createProcessingInstruction('xml-stylesheet',
    'href="style.css" type="text/css"');
  document.insertBefore(pi, document.documentElement);

}

plnkr

或者,使用 XMLHttpRequest() fetch()来请求 .css 文件,创建并附加< style> 元素到文档,使用响应文本执行操作,将 .textContent 样式元素设置为已调整 css text。

Alternatively, use XMLHttpRequest() or fetch() to request .css file, create and append <style> element to document, do stuff with response text, set .textContent of style element to adjusted css text.

这篇关于处理&lt;?xml-stylesheet&gt;类似于&lt; link rel =&quot; stylesheet&quot;&gt;?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-12 13:07