2009-04-15 317 views
4

我有代表一個獨立的字符串(和有效的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串的例子。

回答

14

我可能沒有注意到這一點,但爲什麼不把字符串加載到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'; 
3

在同一頁面上有兩個完整的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

1

而不是提高我其他的答案,我寧願做一個新的,因爲我基本上都需要重新寫它隨你怎麼想工作它和舊的答案可能幫助人們出於其他原因......

因此,提取出從你鏈接到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>,它將會得到舊的風格。

我希望這可以解決您的問題。

1

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

使用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。

0

下面是一些測試代碼,演示如何做到這一點。該代碼從傳遞的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

這是我的代碼,它可以完成你所描述的任務。 有兩點需要注意

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

    } 

}