2011-06-13 66 views
3

我試圖將當前文檔位置存儲在堆棧中,推送startElement,彈出endElement。現在,我使用:Java SAX解析器,存儲屬性

public void startElement(String namespaceURI, String elname, 
         String qName, Attributes atts) throws SAXException { 
    original.append(innerText); 
    original.append("<"); 
    original.append(elname); 
    original.append(">"); 
    docStack.push(new StackElement(elname,atts)); 
.... 

不幸的是當它試圖在以後閱讀的ATT,它提供了錯誤: 致:java.lang.IllegalStateException:屬性只能的startElement的範圍內使用() 。

是否有任何快速可靠的方法來存儲屬性? 另外,是否有更好的方法來做到這一點比爲每個開始標記構造一個新的自定義對象StackElement?

回答

4

當你按下屬性到您的自定義對象堆棧,你是採取實際屬性對象,該對象,根據documentation這樣說:

的ATT - 連接到元素的屬性。如果沒有屬性,它應該是一個空的屬性對象。 這個對象的startElement返回後的價值是不確定的(重點煤礦)

而應該在你的startElement(...)方法捕獲在地圖<字符串,字符串>屬性。這樣你就可以在任何你想要的地方使用它們。

+0

偉大的思想認爲一樣:) – Bohemian 2011-06-13 23:20:36

+0

似乎會有點慢,用每個startElement構造對象,但即使有這個開銷,它仍然應該比DOM更有效率,是正確的嗎? – NoBugs 2011-06-14 00:46:27

+1

它肯定會比DOM更高效,因爲你不會存儲所有東西,只是一些東西。我認爲你對對象創建的擔憂是沒有根據的,因爲Java並不是一種緩慢而笨拙的語言。無論如何,解析完內存和對象都會被清理乾淨。 – 2011-06-14 01:01:05

3

如果Attributes是上下文敏感的,請在StackElement構造函數中從它們中提取您需要的內容(並且不要存儲該引用)。

像這樣的事:

public class StackElement { 

    private Map<String, String> map = new HashMap<String, String>(); 

    public StackElement(String elname, Attributes atts) { 

     for (int i = 0; i < atts.getLength(); i++) { 
      map.put(atts.getQName(i),atts.getValue(i)); 
     } 
    } 
} 

附:這可能看起來像我剽竊@尼古拉斯的答案,但說實話,我已經輸入了它,並在他發佈時正在編寫代碼。

+0

+1 Plagarism! :) – 2011-06-13 22:55:32

+0

我曾經想過把所有東西都拷貝到地圖上,但我認爲這可能效率不高,特別是因爲我不需要每個元素上的所有屬性。這會慢一點,因爲它在每個元素上創建了兩個新類的構造,構造了一個新的StackElement和HashMap,並查詢了所有的屬性!我的問題是,是否有更有效的方式來做到這一點,也許「凍結」的屬性並添加到StackElement? – NoBugs 2011-06-13 23:21:18

+0

get getQName應該是getLocalName – NoBugs 2011-06-14 19:38:57