包括HTML文档的渲染到另一个HTML文档

问题描述:

我有代表一个独立的字符串(和有效的XHTML 1.0严格)的HTML文件,像包括HTML文档的渲染到另一个HTML文档

var html = "<?xml ... <!DOCTYPE ... <html><head><style>...</style></head> 
        <body><table>...</table></body></html>"; 

这个HTML文档的主体包含一个表的CSS样式 被描述在HTML文档的头部。

我也有另一个HTML文档的DOM树。 如何在此DOM树中包含具有正确样式的表的DOM树(如HTML字符串中所述)?

我特别感兴趣的是基于jQuery的解决方案。

编辑:更具体,那我谈论 嵌入this XML-document一个HTML串的例子。

我可能没有注意到这一点,但为什么不把字符串加载到IFRAME中进行渲染 - 这解决了我有两个单独的DOM树和两套单独的CSS规则的问题。

此代码将做到这一点:

$(function() { 
     var $frame = $('<iframe style="width:200px; height:100px; border: 0px;">'); 
     $('body').html($frame); 
     setTimeout(function() { 
       var doc = $frame[0].contentWindow.document; 
       var $body = $('body',doc); 
       $body.html(your_html); 
     }, 1); 
}); 

(这是我从这里升起:putting html inside an iframe (using javascript)):

然后,如果你所关心的IFRAME的大小,你可以将它设置

$frame[0].style.height = $frame[0].contentWindow.document.body.offsetHeight + 'px'; 
$frame[0].style.width = $frame[0].contentWindow.document.body.offsetWidth + 'px'; 

在同一页面上有两个完整的DOM树是没有意义的,所以你需要提取出你想要的并且只用它。

将字符串到jQuery对象,并分析出你所需要的是这样的:

var html = "<html><head><style>...</style></head> 
      <body><table>...</table></body></html>"; 

// Not sure if you are a trying to merge to DOMs together or just 
// trying to place what you want on the page so, I'm going to go 
// with the former as it may be more tricky. 
var other_html = "<html><head><style>...</style></head> 
        <body><!-- some stuff --></body></html>"; 

var jq_html = $(html); 
var jq_other_html = $(other_html); 

var style = jq_html.find('head').find('style'); 
var table_and_stuff = jq_html.find('body').html(); 

jq_other_html.find('head').append(style).end().append(table_and_stuff); 

这也许应该这样做。一旦插入到页面中,浏览器就会自动识别CSS。

注:
对于新的CSS样式表只添加新的风格,而不是覆盖当前的一个(或多个),您必须前插片的头部标记,而不是追加它。所以,最后一行将需要是这样,而不是:

jq_other_html.find('head').prepend(style).end().append(table_and_stuff); 
+0

谢谢,我已经得到了一些类似的工作。现在的问题是,将CSS样式附加到主文档的头部可能会覆盖主文档元素正在使用的某些样式。有没有办法解决这个问题? – Kaarel 2009-04-16 19:25:48

+0

是的,你可以'预先'CSS(与我所描述的方式相同,但是用'prepend(style)'而不是'append(style)'。这样,你现有的CSS将覆盖新附加的CSS CSS,只有新的CSS表格提供的新东西才会起作用。记住,CSS代表'Cascading Style Sheets'。意思是,任何最后列出的和最具体的都将被使用 – KyleFarris 2009-04-20 14:28:48

+0

那么,如果我加入头部,那么现有的主文档中的样式(现在最后)可能会覆盖所包含位的样式,因此向头部添加任何东西都不是一个好的解决方案。理想情况下,包含的DOM树的样式应该是DOM树的本地样式,没有其他样式会影响包含的树。这可能吗? – Kaarel 2009-04-20 19:15:30

而不是提高我其他的答案,我宁愿做一个新的,因为我基本上都需要重新写它随你怎么想工作它和旧的答案可能帮助人们出于其他原因......

因此,提取出从你链接到XML的HTML字符串后,你可以提出它是这样的:

// First we'll extract out the parts of the HTML-string that we need. 
var jq_html = $(html_from_xml); 
var style = jq_html.find('head').find('style').html(); 
var style_string = style.toString(); 
var table_and_stuff = jq_html.find('body').html(); 

// If you want to place it into the existing page's DOM, 
// we need to place it inside a new DIV with a known ID... 
$('body').append('<div id="new_stuff"></div>'); 
$('#new_stuff').html(table_and_stuff); 

// Now, we need to re-write the styles so that they only 
// affect the content of the 'new_stuff' DIV: 
styles_array = style_string.split('}'); 
var new_styles = ''; 
$.each(styles_array,function(i) { 
    if(i<(styles_array.length-1)) { 
     new_styles += "#new_stuff "+styles_array[i]+"}"; 
    } 
}) 
$('head').append('<style type="text/css">'+new_styles+'</style>'); 

这应该是真的。诀窍是CSS会为案例选择最具体的风格。因此,如果您在“newstuff”div中有<td>,它将从新样式表中获取样式。如果你在该“newstuff”div之外有<td>,它将会得到旧的风格。

我希望这可以解决您的问题。

将其插入到嵌入式框架中。

使用question I asked earlier,我有这样一个解决方案:

首先,有一个iframe,一些ID

<iframe id="preview" src="/empty.html"></iframe> 

然后设置样式:

iframe#preview 
{ 
    margin: 30px 10px; 
    width: 90%; 
    height: 800px; 
} 

这里是一个函数将html文本插入该框架(使用jquery)

function preview(html) 
{ 
    var doc = $("#preview")[0].contentWindow.document 
    var body = $('body',doc) 
    body.html(html);  
} 

我用它来成功呈现html的内容,包括可能包含的任何嵌入式CSS。

下面是一些测试代码,演示如何做到这一点。该代码从传递的HTML中提取<style>元素,并将自定义ID添加到所有选择器,然后将HTML注入具有该ID的<div>。由HTML通过这样所有的CSS将只适用于注射表:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
<title>Untitled Document</title> 
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script> 
<script type="text/javascript"> 
$(document).ready(function() { 
    var html = '<?xml version="1.0" encoding="UTF-8"?>\n\ 
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n\ 
    <html xmlns="http://www.w3.org/1999/xhtml">\n\ 
    <head>\n\ 
    <title></title>\n\ 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>\n\ 
    <style type="text/css">\n\ 
    div.dom { background-color: #ace; margin-bottom: 0.5em } table.drs { font-family: monospace; padding: 0.4em 0.4em 0.4em 0.4em; border: 1px solid black; margin-bottom: 2em; background-color: #eee; border-collapse: collapse }\n\ 
    td { vertical-align: top; padding: 0.3em 0.3em 0.3em 0.3em; border: 1px solid black }\n\ 
    td.op { vertical-align: middle; font-size: 110%; border: none }\n\ 
    </style>\n\ 
    </head>\n\ 
    <body><table class="drs"><tr><td><div class="dom">[]</div></td></tr></table></body>\n\ 
    </html>'; 

    var style = html.match(/<style([^>]*)>([^<]*)<\/style>/); 
    var modifiedStyle = style[2].replace(/\s*(} |^|\n)\s*([^{]+)/g, " $1 #inserthere $2"); 

    $(document).find('head').prepend("<style" + style[1] + ">" + modifiedStyle + "</style"); 
    $("#inserthere").append($(html).children()); 
    }); 
</script> 
</head> 
<body> 
<div id="inserthere"> 
</div> 
</body> 
</html> 

很明显,你将不得不修改此为您的情况,但它是一个起点。

这是我的代码,它可以完成你所描述的任务。 有两点需要注意

  1. 出于某种原因,查找()上的“关于即时”的DOM,我从jQuery对象了,可能是有人没有工作,可以找出我做错了有
  2. 为了说明的目的,我已将这个新的dom添加到'body'元素。你可以很轻松地将它添加到你的第二个DOM

var insertStr = "your string here"; 

    var newDom = $(insertStr); // getting [meta style table.drs] 

    // I had to use the array as newDom.find would not work for me which I was expecting would work 
    var styleText = $(newDom[1]).text(); 
    var tableElm = $(newDom[2]); 
    $(newDom[2]).appendTo('body'); 

    var selectors = styleText.split(/{[\s\w\.\(\)':;"#%=/-]*}/); 

    var styles = styleText.match(/{[\s\w\.\(\)':;"#%=/-]*}/g); 



    for (var i =0; i < styles.length; i++) { 
     var style = styles[i]; 

     style = style.replace("{",""); 

    style = style.replace("}",""); 

    if (selectors[i].indexOf("table.drs") > -1) { // identify top-level elm 
     // apply to self 
     tableElm.attr('style',style); 

    } else { 

     // apply to its children 
     tableElm.find(selectors[i]).attr('style',style); 

    } 

}