2011-05-24 38 views
3

的Javadoc org.w3c.dom.Entity狀態:獲得DOM XML實體替換文本中的Xerces

XML並不強制不進行驗證的XML處理器讀取並處理實體聲明的外部子集製作或在參數實體聲明。這意味着在外部子集中聲明的解析實體不需要被某些類的應用程序擴展,並且實體的替換文本可能不可用。當replacement text可用時,相應的實體節點的子列表表示該替換值的結構。否則,子列表是空的。

雖然它沒有引用在內部子集中做出的實體聲明,但是肯定會有一些解析器的配置,它將讀取和處理任何子集中的實體聲明?事實上,我對文檔的閱讀意味着這是默認設置。

在任何情況下,我已經測試(使用的Xerces)以下方法對已在內部子集(如圖所示)已經宣佈,並在外部子集,但foo.hasChildNodes()返回false實體(和foo.getChildNodes()回報foo!)在任何情況下:

// some trivial example XML 
String xml = "<!DOCTYPE example [ <!ENTITY foo 'bar'> ]>\n<example/>"; 
InputStream is = new ByteArrayInputStream(xml.getBytes()); 

// parse 
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
DocumentBuilder builder = factory.newDocumentBuilder(); 
DocumentType docType = builder.parse(is).getDoctype(); 

// retrieve the entity - works fine 
Entity foo = (Entity) docType.getEntities().getNamedItem("foo"); 

// now how to get the entity's replacement text? 

毫無疑問,我失去了一些相當明顯的東西;感謝您的想法。


編輯

它的答案似乎到目前爲止,我的Xerces實現是行爲不端。我會嘗試將所有Xerces庫更新到最新版本,如果解決了我的問題,我會關閉該問題。非常感謝。


UPDATE

更新的Xerces確實已經解決了這個問題,條件是該實體從文檔中引用;如果不是,那麼該節點仍然沒有孩子。我不完全清楚爲什麼會出現這種情況。如果有人能夠解釋發生了什麼並/或者指示我如何強制創建子節點,而不明確引用文檔中的每個實體,則表示感謝。

回答

0

我在Xerces-J用戶郵件列表上詢問了在文檔中沒有引用實體的子節點是否不存在;有Michael Glavassevich helpfully pointed mean old post from Andy Clark解釋如下:

不幸的是(對你而言)這是一項功能。主要出於性能原因,這種方式實施了 。如果一個實體從未在文檔中引用 ,那麼我們永遠不必浪費時間 閱讀它。如果外部實體很大但從未被引用,我們不會浪費時間或內存。

另外,關於命名空間還有一個更深層的問題。 DOM 甚至無法提供幫助。我將解釋...

採取下列文件和外部實體:

<!-- entity.ent --> 
    <hello/> 

    <!-- document.xml --> 
    <!DOCTYPE root [ 
    <!ENTITY entity SYSTEM 'entity.ent'> 
    ]> 
    <root> 
    <sub xmlns='foo'> &entity; </sub> 
    <sub xmlns='bar'> &entity; </sub> 
    </root> 

注意,默認的命名空間是在實體引用的每個點 不同。這意味着 元素將被綁定到不同的名稱空間。所以同一個實體的兩個 實例實際上是不同的元素!

在這種情況下,DOM doctype中的實體節點 應該返回:「foo」命名空間中的子項還是「bar」 命名空間中的子項?

總之,這是一個複雜的問題。

當您查找實體節點並且它沒有 孩子時,您可能最好試着自己閱讀文檔片段 。 Xerces在impl 包中有一個文檔片段掃描程序,可用於此目的。儘管如此,您必須使用 編寫的代碼爲XNI方法中的DOM文檔片段 構建子代。但這並不難。我可以 指出你的例子,如果你需要它。

0

我可能是錯的,但我認爲實體節點將替換文本存儲爲文本值,而不是作爲節點集;這是因爲實體在解析實體定義時實際上並未完全解析:這主要是因爲DTD處理程序是在實際解析過程之前發生的某種預處理程序。 因此請檢查實體節點的文本值而不是子節點列表。

+0

我_think_實體節點的文本內容_應該是它的「文字值」(即包含在實體聲明中的確切文本);而我在「替換文本」之後(即在字符和參數引用被替換之後)。無論如何,看到我的評論[mzjn的答案](http://stackoverflow.com/questions/6115972/obtain-xml-entity-replacement-text-from-dom-in-xerces/6117085#6117085):它返回無論如何,對我來說這是一個空字符串! – eggyal 2011-05-24 21:39:47

+0

對,前我希望是正確的。但後者我不期望是真的;儘管我猜想閱讀DOM規範會很好。無論哪種方式,要公開任何與DTD相關的東西是相當棘手的,因爲它與「常規」XML處理有很大不同,具有不同語法的東西以及完全規則的文本替換,絕對沒有結構意識。 – StaxMan 2011-05-25 15:48:44

+0

謝謝; [相關位](http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core。DOM規範(我的問題中引用的Javadoc已從中提取)的HTML#ID-527DCFF2)明確鏈接到XML規範中的定義;在那裏它特別區分了如上所述的「文字實體價值」和「替代文字」。但是,我認爲對於Entity節點而言,文本內容被定義爲其子節點文本內容的聚合,因此它可能是我最需要的。感謝您的幫助! – eggyal 2011-05-26 06:21:57

0

我不知道爲什麼foo.getChildNodes()不起作用,但我發現了以下內容。如果使用的實體(引用)的文件中,

<!DOCTYPE example [<!ENTITY foo 'bar'>]>\n<example>&foo;</example>

然後替換文本通過

foo.getTextContent()

+0

不幸的是,對我而言,即使在文檔中引用了&foo;,'foo.getTextContent()'也會返回空字符串'「」'。你正在使用什麼解析器實現? – eggyal 2011-05-24 21:35:48

+0

另請參閱我的意見回覆[StaxMan的答案](http://stackoverflow.com/questions/6115972/obtain-xml-entity-replacement-text-from-dom-in-xerces/6117082#6117082):我相信文本內容和替換文本並不完全相同。 – eggyal 2011-05-24 21:48:28

+0

它適用於Xerces 2.10.0。 – mzjn 2011-05-24 22:00:59

1

可我想你可能會被誤替換文本是如何工作的。根據一些閱讀(http://www.javacommerce.com/displaypage.jsp?name=entities.sql&id=18238),它看起來像替代文本像變量一樣工作。所以,在你上面的例子中,你永遠不會引用&foo;實體。如果您運行的代碼示例下面你將看到會發生什麼是&foo;獲取與字符串替換bar

// some trivial example XML 
String xml = "<!DOCTYPE example [ <!ENTITY foo 'bar'> ]><example><foo>&foo;</foo></example>"; 
InputStream is = new ByteArrayInputStream(xml.getBytes()); 

// parse 
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
DocumentBuilder builder = factory.newDocumentBuilder(); 
Document doc = builder.parse(is); 
DocumentType docType = doc.getDoctype(); 

// retrieve the entity - works fine 
Entity foo = (Entity) docType.getEntities().getNamedItem("foo"); 
for(int i = 0; i < foo.getChildNodes().getLength(); i++) { 
    System.out.println(foo.getChildNodes().item(i)); 
} 

你看到印什麼是[#text: bar]這是文本替換XML中。

+0

可悲的是,這正是我不能爲我工作 - 即使我從文檔中引用&foo;(儘管我完全同意這就是它根據文檔應該做的)。在我的情況'foo.getChildNodes()== foo'! '.getLength()'和'.item(0)'分別返回'0'和'null'。你使用什麼實現? – eggyal 2011-05-24 21:45:32

+0

我正在使用JDK 1.6.0_20並從那裏使用'org.w3c.dom.Entity'類。你從上面剪下並粘貼了代碼,沒有任何東西印在控制檯上? – bamana 2011-05-24 22:01:13

+0

確實。 'foo.getChildNodes()。getLength()'返回'0',所以循環從不輸入,並且'System.out.println'永遠不會被調用。 – eggyal 2011-05-24 22:06:46