在 chrome/webkit 中使用 XSLT 转换 HTML 节点

发布于 2024-11-28 06:07:25 字数 1485 浏览 1 评论 0原文

我想使用 XSL 样式表从 XHTML 页面转换 HTML 节点。

这是我使用的函数:

function XSLT(xml,xsl) {
        var tmpElt = document.createElement("div");

        if (window.ActiveXObject){
            //Version IE
            tmpElt.innerHTML = xml.transformNode(xsl);
        }else{
            //Version ECMA
            var xsltProcessor = new XSLTProcessor();
            xsltProcessor.importStylesheet(xsl);
            var result = xsltProcessor.transformToFragment(xml, document);

            var serializer = new XMLSerializer();
            var str = serializer.serializeToString( result );

            tmpElt.innerHTML = str;
        }

        return tmpElt;
}

只要 xml 不是 HTMLElement,该函数就可以在 chrome 上运行。准确地说,这一行:

var result = xsltProcessor.transformToFragment(xml, document);

在 chromium 上返回 null [大多数时间]。在 Firefox 上它表现正常。


我尝试了这个解决方法:

  • 使用outerHTML序列化xml(甚至使用XMLSerializer::serializeToString())
  • 使用新的DOMParser() XSLT解析它的
  • 结果

,但不幸的是outerHTML和innerHTML不会生成正确的XHTML,并且不会呈现有效的XML (它不会关闭单个标签,如


)。,XMLSerializer 也不会关闭单个标签,这是相当的让我惊讶的是。


我注意到,当实际的 HTML 不包含任何自结束标记时,HTML 节点转换会异常有效。因此,我希望 Chrome 在 XSLT 之前使用 XMLSerializer 或 externalHTML 在内部序列化 HTML。

这是 JSFiddle: http://jsfiddle.net/eVbv7/

 

那么,如何在 Chrome 上使用 XSLT HTML 节点呢?我需要一种正确序列化 XHTML 节点的方法,或者任何解决方法都可以。

I want to transform HTML nodes from a XHTML page with an XSL stylesheet.

here's the function I use:

function XSLT(xml,xsl) {
        var tmpElt = document.createElement("div");

        if (window.ActiveXObject){
            //Version IE
            tmpElt.innerHTML = xml.transformNode(xsl);
        }else{
            //Version ECMA
            var xsltProcessor = new XSLTProcessor();
            xsltProcessor.importStylesheet(xsl);
            var result = xsltProcessor.transformToFragment(xml, document);

            var serializer = new XMLSerializer();
            var str = serializer.serializeToString( result );

            tmpElt.innerHTML = str;
        }

        return tmpElt;
}

this will work on chrome as long as xml is not an HTMLElement. precisely, this line:

var result = xsltProcessor.transformToFragment(xml, document);

returns null on chromium[most of the time]. On Firefox it behaves properly.


I tried this workaround:

  • serialize xml with outerHTML ( and even with XMLSerializer::serializeToString() )
  • Parse it with a new DOMParser()
  • XSLT the result

but unfortunately outerHTML and innerHTML won't generate proper XHTML, and don't render valid XML ( it won't close single tags like <hr /> ).,XMLSerializer also won't close single tags, which is quite surprising to me.


I noticed the HTML node transformations will exceptionnaly works when the actual HTML doesn't contain any self closing tags. So I supect Chrome to internally serialize the HTML with XMLSerializer or outerHTML before the XSLT.

Here's the JSFiddle: http://jsfiddle.net/eVbv7/

 

So, how can I XSLT HTML nodes on Chrome? I need either a way to serialize XHTML nodes properly or any workaround will do.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

终弃我 2024-12-05 06:07:25

我再次思考了这个问题,然后推测如果您只是创建一个虚拟 XML DOM 文档,然后从 HTML DOM 文档中 importNode 元素,您是否可能不需要 Chrome 或 Webkit 的自定义克隆或序列化。所以我写了 http://jsfiddle.net/5TNH9/ 并且 Chrome 13 和 Safari 5.1 至少都执行转变。因此,这可能是避免使用自己的脚本代码完全实现序列化或克隆的另一种选择。

但请注意,在 jsfiddle 的测试用例中,Chrome 和 Safari 都出现了重复 br 元素的问题,而 Mozilla 或 Opera 则不会出现这种情况。我目前无法判断该问题是我选择的方法的普遍问题还是特定于该小测试用例的问题。

I pondered the problem again and then speculated whether you might not need custom cloning or serialization for Chrome or Webkit if you simply create a dummy XML DOM document and then importNode the element from the HTML DOM document. So I wrote http://jsfiddle.net/5TNH9/ and indeed both Chrome 13 and Safari 5.1 at least perform the transformation. So that might be another option to avoid implementing serialization or cloning completely with your own script code.

Note however that in that test case on jsfiddle both Chrome and Safari exhibit a problem with duplicated br elements that does not occur with Mozilla or Opera. I am currently not able to tell whether that problem is a general one with the approach I have chosen or something specific to that small test case.

故人如初 2024-12-05 06:07:25

还要注意的一件事是“id”属性必须是唯一的。简单地通过 xsl:copy 传递一些 HTML 将导致重复(参见例如 Martin 的 jsfiddle 的结果):

<div id="d1">
    <h2 align="center">Test</h2>
    <p>This is a test.<br>
        This is a test.<br>
        This is a test.
    </p>
</div>
<div xmlns="http://www.w3.org/1999/xhtml" id="d1">
    <h2 align="center">Test</h2>
    <p>This is a test.<br><br>
        This is a test.<br><br>
        This is a test.
    </p>
</div>

Duplicate id's不同的浏览器可能会以奇怪的方式处理,命名空间问题也是如此。不一定是错误,但肯定是在规范的边界上滑行。

One more thing to beware of is that the "id" attribute must be unique. Simply passing some HTML through xsl:copy will result in duplicates (see the result of e.g. Martin's jsfiddle):

<div id="d1">
    <h2 align="center">Test</h2>
    <p>This is a test.<br>
        This is a test.<br>
        This is a test.
    </p>
</div>
<div xmlns="http://www.w3.org/1999/xhtml" id="d1">
    <h2 align="center">Test</h2>
    <p>This is a test.<br><br>
        This is a test.<br><br>
        This is a test.
    </p>
</div>

Duplicate id's might be handled in odd ways by different browsers, and so will the namespace issues. Not necessarily a bug, but certainly skating at the borders of the specifications.

浮生面具三千个 2024-12-05 06:07:25

我认为 Chrome 和 Safari 可以做你想做的事情,如果 XHTML 节点是使用 XML 解析器解析的文档的一部分,这意味着如果你将原始文档作为 application/xhtml+xml 而不是 text/html 提供,那么你可以应用 XSLT到 XHTML 元素。当然,这样做排除了除 IE 9 之外的任何 IE 版本,除非您能够在服务器上进行内容协商,以向旧 IE 版本提供 text/html ,并向其他浏览器提供 application/xhtml+xml 。

如果您想要转换的节点是解析为 text/html 的文档的一部分,那么我目前不知道解决方案,除了编写自己的代码根据 XML 规则根据需要进行序列化或编写自己的代码克隆 HTML您可以将 DOM 节点转换为 X(HT)ML DOM 节点,并将其传递给transformToFragment。

我知道这个答案并不能直接解决您的问题,而是基于早期不兼容的评论,例如 https: //bugs.webkit.org/show_bug.cgi?id=53375 报告的地方我认为没有一个简单的修复方法。 WebKit 似乎在那里做了一些繁重的工作,一方面尝试实现 Mozilla XSLTProcessor API,另一方面迎合 libxslt 作为其 XSLT 处理器,这种方式导致了一些不兼容性。

I think Chrome and Safari can do what you want if the XHTML nodes are part of an document parsed with the XML parser, meaning if you serve the original document you have as application/xhtml+xml instead of text/html then you can apply XSLT to the XHTML elements. Of course doing that rules out any IE version but IE 9 unless you are able to do content negotiation on the server to serve text/html to old IE versions and application/xhtml+xml to other browsers.

If the nodes you want to transform are part of a document parsed as text/html then I currently don't know a solution, other than writing your own code to serialize as needed according to XML rules or to write your own code cloning the HTML DOM nodes into X(HT)ML DOM nodes you can pass to the transformToFragment.

I know this answer is not directly solving your problem but based on the comments when earlier incompatibilities like https://bugs.webkit.org/show_bug.cgi?id=53375 where reported I don't think there is an easy fix. WebKit seems to do some heavy lifting there, on the one hand trying to implement the Mozilla XSLTProcessor API, on the other hand catering for libxslt as its XSLT processor, that way causing several incompatibilities.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文