简体   繁体   English

使用Sax Parser跳过xml中的元素的最简单方法是什么?

[英]What is the easiest way to skip elements in xml with Sax Parser?

I've been looking around for an answer to this, but all of the SAX resources I find anywhere are a little bit less than I would want them to be. 我一直在寻找答案,但是我在任何地方找到的所有SAX资源都比我希望的少。 I am writing an android application for a restaurant which will give guests access to very long lists through an application rather than paging through a book. 我正在为一家餐馆编写一个android应用程序,它将使客人可以通过应用程序访问很长的列表,而不必翻阅一本书。 My xml looks something like this: 我的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>

It was working well when I only had a couple hundred liquors. 当我只有几百杯酒时,它运转良好。 However, because I use certain element names, such as 'type' and 'price' twice, it is messing things up. 但是,由于我两次使用了某些元素名称,例如“类型”和“价格”,所以事情变得一团糟。 Here is my parser: 这是我的解析器:

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);

}

} }

So, liquor was coming before beer, so, because the parser was seeing "type" before seeing "beer", it was trying to call the 'setType()' function of the Beer object beerTmp, which was never instantiated. 因此,酒先于啤酒,因此,由于解析器在看到“啤酒”之前先看到“类型”,因此它试图调用从未实例化的Beer对象BeerTmp的“ setType()”函数。 I tried to use a boolean, which would wait until the parser saw the first instance of 'beer', but I am getting an empty list, which is really frustrating me, as the almost-identical parser that makes an array of liquors is working magnificently. 我尝试使用布尔值,该布尔值将等待解析器看到“啤酒”的第一个实例,但是我得到的是一个空列表,这确实让我感到沮丧,因为几乎相同的解析器可以制造一系列的酒壮丽。

Is there an easy way to skip the liquors in the file? 有没有一种简单的方法可以跳过文件中的酒类? Am I on the right track with a boolean? 我是否布尔值正确? Should I throw the SAX parser out the window and use something else? 我是否应该将SAX解析器扔到窗外并使用其他东西? Thank you. 谢谢。

The sax parser invokes the callback for all the elements, if you don't want to consider some of them, just do a quick "return;". sax解析器将为所有元素调用回调,如果您不想考虑其中的某些元素,只需快速执行“ return;”即可。 There is no way to filter them out before the parsing. 在解析之前没有办法将它们过滤掉。

Is there an easy way to skip the liquors in the file? 有没有一种简单的方法可以跳过文件中的酒类? Am I on the right track with a boolean? 我是否布尔值正确?

You can use Stack structure to park the data (push) that you'll need to consider later (pop). 您可以使用堆栈结构来存放数据(推送),稍后将需要考虑这些数据(弹出)。

SAX is definitely harder than other XML APIs to tame, for for some cases, it's the only option. SAX绝对比其他XML API难处理,在某些情况下,它是唯一的选择。 So, don't give up with it; 因此,不要放弃它。 before or later you're gonna need it. 之前或之后,您将需要它。

Following simplified virsion works. 以下简化的病毒作品。 Note that 注意

1) your xml have bugs, eg <type>American Rye</liquor> 1)您的xml有错误,例如<type>American Rye</liquor>

2) equalsIgnoreCase is irrelevant since xml is case sensitive. 2)equalsIgnoreCase无关紧要,因为xml区分大小写。

3) JAXB is the best for this job 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);
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM