[英]using SAX parser, how do you parse an xml file which has same name tags but in different elements?
是否可以在 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 以及它們的 getter 和 setter 方法。 這是我的臨時解析器實現。 當我解析 xml 時,我需要將學校名稱、id、學生名稱、id 的值放入 pojo 並返回它。 你能告訴我我應該如何實現差異化的堆棧。 這是我的解析器框架::
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);
}
}
在 SAX 解析器中,您會按文檔順序獲得每個元素。 您必須維護一個堆棧來跟蹤嵌套(處理 startElement 時壓入堆棧,並為 endElement 彈出)。 您可以通過當前在堆棧上的內容來區分不同的<Name>
元素。
或者,只需保留一個變量,告訴您是否遇到了<School>
標記或<Student>
標記,以告訴您看到的是哪種類型的<Name>
。
好吧,我已經好幾年沒有在 Java 中使用 SAX,所以這是我的看法:
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 解析器理解 xml 通常比使用 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(...);
}
}
它和我一起工作
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.