2011-11-05 8 views
1

我目前正在使用JS和嵌入式XPath進行環繞。我正在嘗試創建一個小測試腳本,並發現了一個我想要了解的有趣錯誤。我打電話給評估函數是這樣的:創建新節點時的XPath/Javascript - INVALID_STATE_ERR樹

var result = document.evaluate(
    xpath, 
    document, 
    null, 
    XPathResult.ANY_TYPE); 

在這種情況下,我得到混合結果。字符串,布爾類型和數字類型沒有問題,但UNORDERED_NODE_ITERATOR_TYPE在某種程度上是棘手的。

我的函數來處理結果看起來像這樣:

function nodes(iterator, parentNode) { 
     var cur = iterator.iterateNext(); // do not touch! altering this object causes a INVALID_STATE_ERR Exception 
     var myObj = cur == null || cur == undefined ? undefined : cur.cloneNode(true); 
     var count = 0; 

     while(myObj) { 
      parentNode.appendChild(myObj); 
      var = iterator.iterateNext().cloneNode(true); 
     } 
    } 

但是當我嘗試運行這個功能,我得到一個INVALID_STATE_ERR異常。但爲什麼?我克隆了這些對象,並且我的父節點是一個新創建的元素節點。 (document.createElement('body')應該在最後替換原始的body節點

我需要以另一種方式創建new-body元素嗎?這個異常是因爲新的body元素被附加到當前的文檔樹?我如何做到這一點,如果我不能使用createElement?

+0

請考慮發佈足夠的示例代碼,以便我們重現該問題,也許使用類似http://jsfiddle.net/的網站。我怕'var = iterator.iterateNext()。cloneNode(true);'這樣的語句在語法上甚至不正確。對於XPath DOM API,考慮先對結果進行迭代以收集找到的節點,例如在數組中,然後操作DOM樹。另一方面,一個HTML文檔只有一個'body'元素,那麼爲什麼你需要使用一個迭代器呢?不應該選擇一個單獨的節點嗎? –

+2

我試圖將你的代碼片段轉化爲測試用例來重現問題,在這裏它是:http://jsfiddle.net/pe95g/2/。我認爲這個例子應該可以正常工作,而且它確實在Mozilla和Opera中這樣做,但在Chrome和Safari中,我得到了「INVALID_STATE_ERR:DOM Exception 11」。在我的理解中,這是WebKit DOM實現中的一個錯誤,儘管DOM Level 3 XPath筆記對什麼是「文檔修改」並沒有特別詳細說明,它使「迭代無效」。如果我更改代碼以使用快照(http://jsfiddle.net/WT5Uk/1/),它可以很好地與Mozilla,Opera,Safari和Chrome一起使用。 –

+0

你說得對。我也嘗試過快照,但在那裏我發現了另一個奇怪的失敗。當我使用評估函數時,我使用了定義函數「evaluate(xpathExpression,contextNode,namespaceResolver,resultType,result);」在Firefox中,但相同的調用樣式導致鉻(15.0.874.106)中的錯誤。在那裏我必須這樣調用:「document.evaluate(xpath,document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE)」奇怪!但是你是對的,就像上面運行的Firefox 7中的代碼一樣。(如果你將你的評論添加爲答案,我會接受它,因爲它對我很有幫助) – schlingel

回答

1

我試圖做一個測試用例來重現問題,http://jsfiddle.net/pe95g/2/。它適用於Mozilla和Opera,但與WebKit瀏覽器如Chrome和Safari。在我看來,它不應該因爲被查詢的DOM文檔沒有改變而失敗,只有沒有附加到該文檔的節點在XPath迭代發生時被創建和改變。另一方面,W3C DOM Level 3 XPath note關於什麼是「文檔修改」,這不是很精確「使迭代無效」。

作爲解決方法,我嘗試使用快照代替DOM Level 3 XPath API,http://jsfiddle.net/WT5Uk/1/的迭代器,該方法適用於所有四種主要桌面瀏覽器支持document.evaluate(即Mozilla,Opera,Safari,Chrome )。所以這是我可以建議的唯一解決方法。