Java:使用SAXParser获取下一个子节点

时间:2011-12-22 17:06:25

标签: java xml-parsing

我有以下XML结构:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <person name="foobar">
        <age>45</age>
        <city>SOTown</city>
    </person>
    <person name="tester">
        <age>51</age>
        <city>There</city>
    </person>
</root>

我正在使用SAXParser,我可以获得这样的节点元素(简化):

ArrayList<Person> persons = new ArrayList<Person>();
public void startElement(String uri, String localName,String qName, 
                Attributes attributes) throws SAXException {
if (name.equals("person")){
Person p = new Person();
p.name = attributes.getValue("name");
p.age = ???
p.city = ???
}

public void endElement(String uri, String localName,
        String qName) throws SAXException {

}

问题出在p.agep.city行。

如何获取子节点值?

谢谢。

3 个答案:

答案 0 :(得分:7)

您可以在处理期间更改内容处理程序,这允许您维护状态并执行上下文处理。例如,请考虑这个自包含的示例:

import java.util.ArrayList;
import java.util.List;    
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

public class SAXHandler extends DefaultHandler {

    private XMLReader reader;
    private List<Person> people = new ArrayList<Person>();

    public static void main(String[] args) {
        try {
            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser saxParser = factory.newSAXParser();
            SAXHandler tester = new SAXHandler(saxParser.getXMLReader());
            saxParser.parse("workbook.xml", tester);
            System.out.println(tester.people);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public SAXHandler(XMLReader reader) {
        this.reader = reader;
    }

    public Person addPerson(Person person) {
        this.people.add(person);
        return person;
    }

    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {
        if ("person".equals(qName)) {
            String name = attributes.getValue("name");
            this.reader.setContentHandler(new PersonHandler(this.reader, this,
                    name));
        }
        System.out.println("Start Element: " + qName);
    }
}

请注意,只要遇到setContentHandler元素,我们就会personPersonHandler看起来像这样:

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

public class PersonHandler extends DefaultHandler {

    private Person currPerson;
    private StringBuilder content;
    private XMLReader reader;
    private SAXHandler parentHandler;

    public PersonHandler(XMLReader reader, SAXHandler parentHandler, String name) {
        this.reader = reader;
        this.parentHandler = parentHandler;
        this.currPerson = new Person(name);
        this.content = new StringBuilder();
    }

    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {
        this.content.setLength(0);
        System.out.println("PersonHandler::Start Element: " + qName);
    }

    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        if ("age".equals(qName)) {
            this.currPerson.setAge(this.content.toString());
        } else if ("city".equals(qName)) {
            this.currPerson.setCity(this.content.toString());
        } else if ("person".equals(qName)) {
            this.parentHandler.addPerson(this.currPerson);
            this.reader.setContentHandler(this.parentHandler);
        }
        System.out.println("PersonHandler::End Element: " + qName);
    }

    public void characters(char ch[], int start, int length)
            throws SAXException {
        this.content.append(ch, start, length);
    }

}

请注意,每当我们处理完person时,我们都会将内容处理程序重置为父处理程序。

为了完整性,这里是一个(非常)最小Person

public class Person {

    private String name;
    private String age;
    private String city;

    public Person(String name) {
        this.name = name;
    }

    public void setAge(String string) {
        this.age = string;
    }

    public void setCity(String string) {
        this.city = string;
    }

    public String toString() {
        return this.name + " " + this.age + " " + this.city;
    }
}

此代码将输出:

Start Element: root
Start Element: person
PersonHandler::Start Element: age
PersonHandler::End Element: age
PersonHandler::Start Element: city
PersonHandler::End Element: city
PersonHandler::End Element: person
Start Element: person
PersonHandler::Start Element: age
PersonHandler::End Element: age
PersonHandler::Start Element: city
PersonHandler::End Element: city
PersonHandler::End Element: person

答案 1 :(得分:4)

你不能直接,你必须设置一个布尔实例变量 表示您现在位于person元素内并设置了人员属性 在endElement方法中。字符内容传递给 characters方法,因为解析器是必须附加到缓冲区 允许多次调用此方法。

StringBuilder content = new StringBuilder();
boolean inPerson = false;
Person person;

// characters can be called multiple times per element, so aggregate the content in a StringBuilder
public void characters(char[] ch, int start, int length) throws SAXException {
    content.append(ch, start, length);
}

public void startElement(String uri, String localName,String qName, Attributes attributes) throws SAXException {
    // reset the character buffer
    content.setLength(0);
    if (localName.equals("person")) {
        this.person = new Person();
        this.person.name = attributes.getValue("name");
        this.inPerson = true;
    } 
}

public void endElement(String uri, String localName, String qName) throws SAXException {
    if (inPerson) {
        if (localName.equals("age")) {
            this.person.age = Integer.parseInt(content.toString());
        } else if (localName.equals("city")) {
            this.person.city = content.toString();
        } else if (localName.equals("person")) {
            this.inPerson = false;
        }
    }
}

答案 2 :(得分:0)

使用此代码:替换top ...中的开始和结束元素以及声明Person类对象

ArrayList<Person> persons = new ArrayList<Person>();
String content;
Person p;

public void startElement(String uri, String localName,String qName, 
                Attributes attributes) throws SAXException 
{
    if (localName.equals("person")) {
        p = new Person();
        p.name = attributes.getValue("name");
    }
}

public void endElement(String uri, String localName,
        String qName) throws SAXException {

    if (localName.equals("age"))  {
        p.age = = Integer.parseInt(content.toString());
    } 

    if (localName.equals("city")) {          
        p.city  = content;
    } 

    if (localName.equals("person")) {
        persons.add(p);
    }
}

public void characters(char[] ch, int start, int length)
            throws SAXException {
    content= new String(ch, start, length); 
}

有任何疑问或建议吗?欢迎您...