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

时间:2011-08-08 16:09:28

标签: javascript xslt webkit

我想使用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);

在大多数情况下在铬上返回null。在Firefox上,它的行为正常。


我尝试了这种解决方法:

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

但遗憾的是,outerHTML和innerHTML不会生成正确的XHTML,也不会呈现有效的XML(它不会关闭像<hr />这样的单个标记。),XMLSerializer也不会关闭单个标记,这是我很惊讶。


我注意到当实际HTML不包含任何自闭标记时,HTML节点转换将异常起作用。所以我认为Chrome在XSLT之前使用XMLSerializer或outerHTML在内部序列化HTML。

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

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

3 个答案:

答案 0 :(得分:4)

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

但请注意,在jsfiddle的测试用例中,Chrome和Safari都存在重复br元素的问题,这些元素不会出现在Mozilla或Opera中。我目前无法判断这个问题是否与我选择的方法或特定于该小测试用例的问题一致。

答案 1 :(得分:3)

另外需要注意的是&#34; id&#34;属性必须是唯一的。简单地通过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>

不同的浏览器可能会以奇怪的方式处理重复的ID,命名空间也会发生问题。不一定是一个错误,但肯定是在规范的边界滑冰。

答案 2 :(得分:1)

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

如果要转换的节点是解析为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处理器,这种方式导致了几种不兼容性。