我一直在寻找答案,但我找到的所有SAX资源都比我想要的要少一些。我正在为一家餐厅编写一个Android应用程序,它将通过应用程序访问非常长的列表,而不是通过书籍进行分页。我的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>
当我只有几百份酒时它运作良好。但是,因为我使用了某些元素名称,例如'type'和'price'两次,所以它会搞砸了。这是我的解析器:
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);
}
}
所以,酒是在啤酒之前来的,所以,因为解析器在看到“啤酒”之前看到了“类型”,它试图调用Beer对象beerTmp的'setType()'函数,它从未实例化过。我试图使用一个布尔值,它会等到解析器看到'啤酒'的第一个实例,但是我得到一个空列表,这真让我感到沮丧,因为几乎相同的解析器使得一系列酒类正在工作辉煌。
有没有简单的方法可以跳过文件中的酒类?我是否在布尔的正确轨道上?我应该将SAX解析器抛出窗口并使用其他东西吗?谢谢。
答案 0 :(得分:0)
sax解析器调用所有元素的回调,如果你不想考虑其中的一些,只需快速“返回”。在解析之前无法过滤掉它们。
有没有简单的方法可以跳过文件中的酒类?我是否使用布尔值在正确的轨道上?
您可以使用Stack结构来停放您稍后需要考虑的数据(推送)。(/ p>
SAX肯定比其他XML API更难驯服,因为在某些情况下,它是唯一的选择。所以,不要放弃它;之前或之后你会需要它。
答案 1 :(得分:0)
遵循简化的virsion工作。注意
1)你的xml有bug,例如<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);
}
}
}
}