используя Sax parser, как вы анализируете xml-файл, который имеет одинаковые теги имен, но в разных элементах?

можно ли дать выражения пути в синтаксическом анализаторе SAX? У меня есть XML-файл, который имеет несколько одинаковых тегов имен, но они находятся в другом элементе. Есть ли способ различать их? Вот XML:

<Schools>
    <School>
        <ID>335823</ID> 
        <Name>Fairfax High School</Name> 
        <Student>
            <ID>4195653</ID>
            <Name>Will Turner</Name>
        </Student>
        <Student>
            <ID>4195654</ID>
            <Name>Bruce Paltrow</Name>
        </Student>
        <Student>
            <ID>4195655</ID>
            <Name>Santosh Gowswami</Name>
        </Student>
    </School>
    <School>
        <ID>335824</ID> 
        <Name>FallsChurch High School</Name> 
        <Student>
            <ID>4153</ID>
            <Name>John Singer</Name>
        </Student>
        <Student>
            <ID>4154</ID>
            <Name>Shane Warne</Name>
        </Student>
        <Student>
            <ID>4155</ID>
            <Name>Eddie Diaz</Name>
        </Student>
    </School>
</Schools>

Я хочу различать имя и идентификатор ученика от имени и идентификатора школы.

Спасибо за ответ:

Я создал студент pojo, который имеет следующие поля-school_id, school_name, student_id и student_name и методы геттера и сеттера для них. Это моя временная реализация парсера. Когда я анализирую xml, мне нужно поместить значения school name, id, student name, id в pojo и вернуть его. Можете ли вы сказать мне, как я должен реализовать стек для дифференциации. Это мой парсер framework::

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

public class HandleXML extends DefaultHandler {

    private student info;
    private boolean school_id = false;
    private boolean school_name = false;
    private boolean student_id = false;
    private boolean student_name = false;
    private boolean student = false;
    private boolean school = false;


    public HandleXML(student record) {
        super();
        this.info = record;
        school_id = false;
        school_name = false;
        student_id = false;
        student_name = false;
        student = false;
        school = false;
    }

    @Override
    public void startElement(String uri, String localName,
            String qName, Attributes attributes)
            throws SAXException {
    if (qName.equalsIgnoreCase("student")) {
            student = true;
        }
    if (qName.equalsIgnoreCase("school")) {
            school_id = true;
        }
    if (qName.equalsIgnoreCase("school_id")) {
            school_id = true;
        }
    if (qName.equalsIgnoreCase("student_id")) {
            student_id = true;
        }
    if (qName.equalsIgnoreCase("school_name")) {
            school_name = true;
        }
    if (qName.equalsIgnoreCase("student_name")) {
            student_name = true;
        }
    }

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

    @Override
    public void characters(char ch[], int start, int length)
            throws SAXException {

        String data = new String(ch, start, length);

    }
}

5 ответов


Ну, я не играл в течение многих лет с саксофоном на Java, так что вот мой взгляд на это:

package play.xml.sax;

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

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

public class Test1 {
    public static void main(String[] args) {
        SAXParserFactory spf = SAXParserFactory.newInstance();
        SchoolsHandler handler = new SchoolsHandler();
        try {
            SAXParser sp = spf.newSAXParser();
            sp.parse("schools.xml", handler);
            System.out.println("Number of read schools: " + handler.getSchools().size());
        } catch (SAXException se) {
            se.printStackTrace();
        } catch (ParserConfigurationException pce) {
            pce.printStackTrace();
        } catch (IOException ie) {
            ie.printStackTrace();
        }
    }
}

class SchoolsHandler extends DefaultHandler {
    private static final String TAG_SCHOOLS = "Schools";
    private static final String TAG_SCHOOL = "School";
    private static final String TAG_STUDENT = "Student";
    private static final String TAG_ID = "ID";
    private static final String TAG_NAME = "Name";

    private final Stack<String> tagsStack = new Stack<String>();
    private final StringBuilder tempVal = new StringBuilder();

    private List<School> schools;
    private School school;
    private Student student;

    public void startElement(String uri, String localName, String qName, Attributes attributes) {
        pushTag(qName);
        tempVal.setLength(0);
        if (TAG_SCHOOLS.equalsIgnoreCase(qName)) {
            schools = new ArrayList<School>();
        } else if (TAG_SCHOOL.equalsIgnoreCase(qName)) {
            school = new School();
        } else if (TAG_STUDENT.equalsIgnoreCase(qName)) {
            student = new Student();
        }
    }

    public void characters(char ch[], int start, int length) {
        tempVal.append(ch, start, length);
    }

    public void endElement(String uri, String localName, String qName) {
        String tag = peekTag();
        if (!qName.equals(tag)) {
            throw new InternalError();
        }

        popTag();
        String parentTag = peekTag();

        if (TAG_ID.equalsIgnoreCase(tag)) {
            int id = Integer.valueOf(tempVal.toString().trim());
            if (TAG_STUDENT.equalsIgnoreCase(parentTag)) {
                student.setId(id);
            } else if (TAG_SCHOOL.equalsIgnoreCase(parentTag)) {
                school.setId(id);
            }
        } else if (TAG_NAME.equalsIgnoreCase(tag)) {
            String name = tempVal.toString().trim();
            if (TAG_STUDENT.equalsIgnoreCase(parentTag)) {
                student.setName(name);
            } else if (TAG_SCHOOL.equalsIgnoreCase(parentTag)) {
                school.setName(name);
            }
        } else if (TAG_STUDENT.equalsIgnoreCase(tag)) {
            school.addStudent(student);
        } else if (TAG_SCHOOL.equalsIgnoreCase(tag)) {
            schools.add(school);
        }
    }

    public void startDocument() {
        pushTag("");
    }

    public List<School> getSchools() {
        return schools;
    }

    private void pushTag(String tag) {
        tagsStack.push(tag);
    }

    private String popTag() {
        return tagsStack.pop();
    }

    private String peekTag() {
        return tagsStack.peek();
    }
}

class School {
    private int id;
    private String name;
    private List<Student> students = new ArrayList<Student>();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void addStudent(Student student) {
        students.add(student);
    }

    public List<Student> getStudents() {
        return students;
    }
}

class Student {
    private int id;
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
}

schools.xml содержит пример XML. Обратите внимание, что я запихнул все в один файл, но это только для того, чтобы я просто играл.


в парсере SAX вам дается каждый элемент в порядке документа. Вы должны поддерживать стек для отслеживания вложенности (нажмите на стек при обработке startElement и pop для endElement). Вы можете различать разные <Name> элементы по тому, что в настоящее время находится в стеке.

в качестве альтернативы, просто держите переменную, которая говорит вам, если вы встретили <School> тег или <Student> тег, чтобы сказать вам, какой тип <Name> вы видите.


да, понимание xml с помощью синтаксического анализатора SAX обычно немного сложнее, чем работа с DOM. в принципе, вам нужно поддерживать состояние / контекст в вашем синтаксическом анализаторе SAX, чтобы вы могли различать эти ситуации.

обратите внимание, что другим ключом к реализации обработчика SAX является понимание того, что значения могут быть разделены на несколько событий персонажа.


Sax основан на событии, через обратные вызовы вы можете прочитать документ XML последовательно. Sax хорош для чтения больших XML-документов, так как весь документ не загружается в память. Вы можете посмотреть на XPath-выражения, например,

XPathFactory xPathFactory = XPathFactory.newInstance();
XPath xPath = xPathFactory.newXPath();
String expression = "/Schools/school/ ...";
XPathExpression xPathExpression = xPath.compile(expression);
// Compile the expression to get a XPathExpression object.
Object result = xPathExpression.evaluate(xmlDocument);

private boolean isInStudentNode;
...................................................    

public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
    // enter node Student
    if(qName.equalEgnoreCase("Student"){
       isInStudentNode = true;
    }
    ...
}

public void endElement(String uri, String localName, String qName) throws SAXException {
    // end node Student
    if(qName.equalEgnoreCase("Student"){
       isInStudentNode = false;
       ...........
    }

    // end node Name (school|student)
    if(qName.equalEgnoreCase("Name"){
        if(isInStudentNode) student.setName(...);
        else school.setName(...);
    }
}

его работа со мной