2013-01-09 73 views
0

我一直在尋找答案,但我在任何地方找到的所有SAX資源都比我想要的要少。我正在爲一家餐廳編寫一個Android應用程序,它將通過應用程序爲客人提供訪問非常長的列表,而不是通過書籍進行分頁。我的xml看起來像這樣:使用Sax Parser在xml中跳過元素的最簡單方法是什麼?

<bar> 
    <liquor> 
     <type>American Rye</type> 
     <distillery>Sazerac<distillery> 
     <bottling>18 Year</bottling> 
     <place>Frankfort, KY</place> 
     <proof>90</proof> 
     <price>20<price> 
    </liquor> 

    <beer> 
     <type>American Microbrew</type> 
     <brewery>New Belgium</brewery> 
     <bottling>La Folie Sour Brown 750ml</bottling> 
     <place>Fort Collins, CO</place> 
     <price>20</price> 
    </beer> 
</bar> 

當我只有幾百個酒時,它工作得很好。但是,由於我使用了某些元素名稱,例如「類型」和「價格」兩次,所以這會讓事情變得糟糕。這裏是我的解析器:

public class BeerParser extends DefaultHandler { 

private ArrayList<Beer> BeerL; 
private boolean pastTheLiquor = false; 

public ArrayList<Beer> getItems(String ArrayType){ 
    ArrayList<Beer> tmpItem = new ArrayList<Beer>(); 
    for (Beer beer : BeerL){ 
     if (beer.getType().equals(ArrayType)){ 
     tmpItem.add(beer); 
      } 
     } 
    return tmpItem; 
} 


InputStream barXmlInputStream; 

String tmpValue; 


Beer beerTmp; 



public BeerParser(InputStream barXmlInputStream) { 



    this.barXmlInputStream = barXmlInputStream; 

    BeerL = new ArrayList<Beer>(); 

    parseDocument(); 

    printDatas(); 

} 

private void parseDocument() { 



    SAXParserFactory factory = SAXParserFactory.newInstance(); 

    try { 

     SAXParser parser = factory.newSAXParser(); 

     parser.parse(barXmlInputStream, this); 



    } catch (ParserConfigurationException e) { 

     System.out.println("ParserConfig error"); 

    } catch (SAXException e) { 

     System.out.println("SAXException : xml not well formed"); 

    } catch (IOException e) { 

     System.out.println("IO error"); 

    } 

} 

private void printDatas() { 


    for (Beer tmpB : BeerL) { 

     System.out.println(tmpB.toString()); 

    } 


} 

@Override 

public void startElement(String s, String s1, String elementName, Attributes attributes) throws SAXException { 


    if (elementName.equalsIgnoreCase("beer")) { 

     pastTheLiquor = true; 
     beerTmp = new Beer(); 



    } 

} 

@Override 

public void endElement(String s, String s1, String element) throws SAXException { 


    if (element.equals("beer")) { 

      BeerL.add(beerTmp); 

     } 
    if (pastTheLiquor){ 
     if (element.equalsIgnoreCase("type")) { 

      beerTmp.setType(tmpValue); 

     } 
     if (element.equalsIgnoreCase("brewery")) { 

      beerTmp.setBrewery(tmpValue); 

     } 
     if (element.equalsIgnoreCase("bottling")) { 

      beerTmp.setBottling(tmpValue); 
      beerTmp.hasBottling = true; 

     } 

     if (element.equalsIgnoreCase("price")) { 

      beerTmp.setPrice(tmpValue); 

     } 

     if (element.equalsIgnoreCase("place")) { 

      beerTmp.setPlace(tmpValue); 

     } 
    } 

} 



@Override 

public void characters(char[] ac, int i, int j) throws SAXException { 

    tmpValue = new String(ac, i, j); 

} 

}

所以,酒是啤酒之前到來,那麼,因爲解析器是看到「式的」看到「啤酒」之前,它試圖撥打「的setType( )'啤酒對象beerTmp的函數,它從來沒有實例化過。我試圖使用一個布爾值,它將等到分析器看到「啤酒」的第一個實例,但我得到一個空列表,這真令人沮喪,因爲幾乎完全相同的分析器使得一系列酒類正在工作輝煌。

有沒有簡單的方法來跳過文件中的酒?我在布爾的正確軌道上?我應該將SAX解析器從窗口中移出並使用其他內容嗎?謝謝。

+0

源代碼會更容易閱讀沒有所有的空行! – MrSmith42

+0

正如我在回覆另一篇文章時所說的,對於這樣的工作來說,SAX是錯誤的工具。 DOM和XPath是正確的工具,可以爲您提供更少的代碼和更多的靈活性。但由於某些原因,人們對SAX感興趣。 – parsifal

+0

@parsifal有很多理由說,爲什麼要選擇SAX而不是DOM,而不是執行某些操作所需的代碼。例如,一個巨大的XML不能用DOM解析。或者來自遠程流的XML緩慢生成並需要連續處理,最好使用SAX進行分析。我認爲,如果dereksalerno選擇了SAX,那麼有很好的理由。順便說一句,SAX遠遠低估了。 –

回答

0

繼簡化的virsion作品。需要注意的是

1)你的XML有錯誤,如<type>American Rye</liquor>

2)equalsIgnoreCase是無關緊要的,因爲XML是大小寫敏感的。

3)JAXB是最適合這個工作

public class BeerParser extends DefaultHandler { 
    private List<Beer> list = new ArrayList<>(); 
    private Beer beer; 
    private String element; 

    public static void main(String[] args) throws Exception { 
     SAXParserFactory factory = SAXParserFactory.newInstance(); 
     SAXParser parser = factory.newSAXParser(); 
     BeerParser bp = new BeerParser(); 
     parser.parse(new File("1.xml"), bp); 
     System.out.println(bp.list); 
    } 

    @Override 
    public void startElement(String s, String s1, String element, Attributes attributes) { 
     if (element.equals("beer")) { 
      beer = new Beer(); 
     } 
     this.element = element; 
    } 

    @Override 
    public void endElement(String s, String s1, String element) { 
     if (element.equals("beer")) { 
      list.add(beer); 
      beer = null; 
     } 
    } 

    @Override 
    public void characters(char[] ac, int i, int j) { 
     if (beer != null) { 
      String value = new String(ac, i, j); 
      if (element.equals("type")) { 
       beer.setType(value); 
      } else if (element.equals("brewery")) { 
       beer.setBrewery(value); 
      } else if (element.equals("bottling")) { 
       beer.setBottling(value); 
      } else if (element.equals("price")) { 
       beer.setPrice(value); 
      } else if (element.equals("place")) { 
       beer.setPlace(value); 
      } 
     } 
    } 
} 
+0

我使用了啤酒!=邏輯,現在看起來如此顯而易見!非常感謝,我因處理這個文件而變得如此不知所措呃,我忘了簡單的java程序。 – dereksalerno

0

薩克斯解析器調用所有元素的回調,如果你不想考慮其中的一些元素,只需做一個快速的「返回」。在解析之前無法將它們濾除。

有沒有簡單的方法來跳過文件中的酒?我在布爾的正確軌道上?

您可以使用Stack結構停放稍後需要考慮的數據(推送)(彈出)。

SAX絕對比其他XML API更難馴服,因爲在某些情況下,它是唯一的選擇。所以,不要放棄它;之前或之後你會需要它。

相關問題