DOM을 사용하여 XML 문서를 파싱할 때는 XML 문서 전체를 읽고 빌드해야 합니다. XML 문서를 작동하기 위해 전체 DOM 트리의 메모리 Document 개체에 있습니다. 이 경우 XML 문서의 용량이 특히 크면 컴퓨터 메모리를 많이 소모하게 되며, 심한 경우에는 메모리 오버플로가 발생할 수 있습니다.
SAX 구문 분석을 사용하면 전체 문서가 로드될 때까지 기다릴 필요 없이 문서를 읽을 때 문서를 처리할 수 있습니다.
DefaultHandler
을 상속받아 SAX 파서를 개발한다. [참고] SAX 메인을 사용한다 XML 문서를 구문 분석하기 위한 것이며 요소를 수정, 삭제 또는 추가할 수 없습니다.
Sax는 푸시 메커니즘이므로 Sax 파서를 생성합니다. 파서는 XML 문서에서 콘텐츠를 찾으면 이를 알려줍니다(Java Swing의 이벤트 수신과 다소 유사하게 이벤트를 사용자에게 푸시함). 이러한 결과로 무엇을 할지 결정하는 것은 프로그래머의 몫입니다.
sax 기반 프로그램에는 가장 일반적으로 사용되는 5가지 sax 이벤트가 있습니다.
1.startDocument()–> 파서가 문서 스캔을 시작한다고 알려줍니다.
2.endDocument()–> 파서가 문서의 끝을 찾았음을 알려줍니다.
3.startElement()–> 파서가 시작 태그를 찾았음을 알려줍니다. 이 이벤트는 태그 이름, 모든 속성 이름 및 요소 값을 알려줍니다. 4.characters()–>는 파서가 일부 텍스트를 찾았음을 알려주고 문자 배열, 배열의 오프셋 및 길이 오프셋을 가져옵니다.
5.endElement()–> 파서가 종료 태그를 찾았음을 알려줍니다.
<?xml version="1.0" encoding="utf-8" standalone="no"?><班级> <学生 地址="香港"> <名字>周小星</名字> <年龄>23</年龄> <介绍>学习刻苦</介绍> </学生> <学生 地址="澳门"> <名字>林晓</名字> <年龄>25</年龄> <介绍>是一个好学生</介绍> </学生></班级>
[단계]:
1. SAXParserFactory를 사용하여 SAX 구문 분석 팩토리를 만듭니다. 🎜>SAXParserFactory spf = SAXParserFactory.newInstance();
2. SAX 파싱 팩토리를 통해 파서 개체를 얻습니다.
SAXParser sp = spf.newSAXParser();
3. 파싱 개체를 이벤트 핸들러 개체와 연결합니다.
sp.parse("src/myClass.xml",new MyHandler());
여기에
가 있어야 합니다. 직접 정의하고을 상속받아야 하며, MyHandler
클래스에서 위에서 언급한 5개의 sax 이벤트 메서드를 다시 작성해야 합니다. 물론 필요한 것만 다시 작성할 수도 있습니다. DefaultHandler
예를 들어 지금 제가 작성한 MyHandler
은 다음과 같습니다.
class MyHandler extends DefaultHandler{ /** * 发现文档开始,该函数只会被调用一次 */ @Override public void startDocument() throws SAXException { System.out.println("startDocument"); } /** * 发现文档结束,该函数只会被调用一次 */ @Override public void endDocument() throws SAXException { System.out.println("endDocument"); } /** * 发现XML中的一个元素开始,会被反复调用 */ @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { System.out.println("元素名称:"+qName); } /** * 发现XML中的一个元素结束,会被反复调用 */ @Override public void endElement(String uri, String localName, String qName) throws SAXException { } /** * 发现XML文件中的文本,会被反复调用 */ @Override public void characters(char[] ch, int start, int length) throws SAXException { // 显示文本内容 String text = new String(ch,start,length); if(!text.trim().equals("")){ System.out.println(text); } } }
MyHandler
실행 결과는 다음과 같습니다.
보시다시피 , 이것은 XML 문서입니다. 일종의 순회가 있으며 sax가 할 수 있는 것은 순회뿐입니다.
이제 이러한 요구 사항이 있는 경우:只显示所有学生的姓名和年龄,不显示学生的介绍,怎么实现呢?
메소드에서 이름 요소인지 연령 요소인지 식별합니다. 그렇다면 다음과 같이 MyHandler
메소드에서 해당 텍스트를 가져옵니다. startElement
characters
private boolean isName = false;private boolean isAge = false;2. 메소드에 판정 추가
@Overridepublic void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException { if(qName.equals("名字")){ this.isName = true;
}else if(qName.equals("年龄")){ this.isAge = true;
}
}
startElement
3. 식별자 Text
@Overridepublic void characters(char[] ch, int start, int length) throws SAXException { // 显示文本内容 String text = new String(ch,start,length); if(!text.trim().equals("")&&(isName||isAge)){ System.out.println(text); } isName = false; isAge = false; }를 기반으로 마지막으로 두 개의 부울 변수를 false로 재설정해야 합니다.
characters
실행 결과는 다음과 같습니다.
1. SAX 파싱
SAX 구문 분석을 사용하면 전체 문서가 로드될 때까지 기다릴 필요 없이 문서를 읽을 때 문서를 처리할 수 있습니다.
DefaultHandler
1.1. SAX 파싱 메커니즘
1.startDocument()–>告诉你解析器发现了文档的开始,告诉你解析器开始扫描文档
2.endDocument()–>告诉你解析器发现了文档结尾
3.startElement()–>告诉你解析器发现了一个起始标签,该事件告诉你标签的名称、该元素所有的属性名和值
4.characters()–>告诉你解析器发现了一些文本,将得到一个字符数组,该数组的偏移量和一个长度偏移量,有这三个变量你可以得到解析器发现的文本
5.endElement()–>告诉你解析器发现了一个结束标签,该事件告诉你元素的名称
依然使用DOM解析中用到的XML例子,如下:
<?xml version="1.0" encoding="utf-8" standalone="no"?><班级> <学生 地址="香港"> <名字>周小星</名字> <年龄>23</年龄> <介绍>学习刻苦</介绍> </学生> <学生 地址="澳门"> <名字>林晓</名字> <年龄>25</年龄> <介绍>是一个好学生</介绍> </学生></班级>
【步骤】:
1.使用SAXParserFactory创建SAX解析工厂
SAXParserFactory spf = SAXParserFactory.newInstance();
2.通过SAX解析工厂得到解析器对象
SAXParser sp = spf.newSAXParser();
3.将解析对象和事件处理器对象关联
sp.parse("src/myClass.xml",new MyHandler());
这里的MyHandler
需要自己定义,并且它要继承DefaultHandler
,然后在MyHandler
类中重写上文提到的5个sax事件方法,当然也可以只重写自己需要的。
比如现在我写的MyHandler
如下:
class MyHandler extends DefaultHandler{ /** * 发现文档开始,该函数只会被调用一次 */ @Override public void startDocument() throws SAXException { System.out.println("startDocument"); } /** * 发现文档结束,该函数只会被调用一次 */ @Override public void endDocument() throws SAXException { System.out.println("endDocument"); } /** * 发现XML中的一个元素开始,会被反复调用 */ @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { System.out.println("元素名称:"+qName); } /** * 发现XML中的一个元素结束,会被反复调用 */ @Override public void endElement(String uri, String localName, String qName) throws SAXException { } /** * 发现XML文件中的文本,会被反复调用 */ @Override public void characters(char[] ch, int start, int length) throws SAXException { // 显示文本内容 String text = new String(ch,start,length); if(!text.trim().equals("")){ System.out.println(text); } } }
运行结果如下:
可以看到,这是对XML文档的一种遍历,而sax能够做的也只是遍历了。
那么,如果现在我们有这样一个需求:只显示所有学生的姓名和年龄,不显示学生的介绍,怎么实现呢?
我们可以在MyHandler
类中定义两个布尔变量isName和isAge,在startElement
方法中标识是否是姓名元素或者年龄元素,如果是的话才在characters
方法中获取对应的文本,如下:
1.定义两个布尔变量
private boolean isName = false;private boolean isAge = false;
2.在startElement
方法中添加判断
@Overridepublic void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if(qName.equals("名字")){ this.isName = true; }else if(qName.equals("年龄")){ this.isAge = true; } }
3.在characters
方法中根据标识符进行判断是否获取文本
@Overridepublic void characters(char[] ch, int start, int length) throws SAXException { // 显示文本内容 String text = new String(ch,start,length); if(!text.trim().equals("")&&(isName||isAge)){ System.out.println(text); } isName = false; isAge = false; }
最后要记得将两个布尔变量复位成false。
运行结果如下:
以上就是XML—XML解析之SAX的内容,更多相关内容请关注PHP中文网(www.php.cn)!