定义XML语法分析基本元素
为了把一个XML文件处理成为上面提到的简化的DOM树模型,我们必须定义一些基本的语法分析规则。使用这些规则,语法分析程序就能容易地从输入的XML文件中提取标记或者文本块。
第一个是peek,从输入的XML文件中返回下一个字符,而实际上则不必从下层流中获得这个字符。通过保持输入流的完整性,高级函数比如readTag和readText(后面将介绍)可以更加容易地根据它们接下来期待的字符获取需要的内容。
- private int peek() throws IOException {
- reader.mark(1);
- int result = reader.read();
- reader.reset();
- return result;
- }
下一个方法是skipWhitespce,作用是跳过输入的XML流中的空格、制表符或者回车符。
- private void skipWhitespace() throws IOException {
- while (Character.isWhitespace((char) peek())) {
- reader.read();
- }
- }
在创建了如上所述的这两个方法后,我们就可以写一个函数从输入文件中检索XML标记。
- private String readTag() throws IOException {
- skipWhitespace();
- StringBuffer sb = new StringBuffer();
- int next = peek();
- if (next != '<') {
- throw new IOException
- ("Expected > but got " + (char) next);
- }
- sb.append((char)reader.read());
- while (peek() != '>') {
- sb.append((char)reader.read());
- }
- sb.append((char)reader.read());
- return sb.toString();
- }
和peek方法联合使用,readTag函数只获得一个标记的内容,而让别的函数去处理其他的内容。 最后的一个方法是readText函数,用来读取XML标记之间的文本。
- private String readText() throws IOException {
- int[] cdata_start = {'<', '!',
- '[', 'C', 'D', 'A', 'T', 'A', '['};
- int[] cdata_end = {']', ']', '>'};
- StringBuffer sb = new StringBuffer();
- int[] next = new int[cdata_start.length];
- peek(next);
- if (compareIntArrays(next, cdata_start) == true) {
- // CDATA
- reader.skip(next.length);
- int[] buffer = new int[cdata_end.length];
- while (true) {
- peek(buffer);
- if (compareIntArrays
- (buffer, cdata_end) == true) {
- reader.skip(buffer.length);
- break;
- } else {
- sb.append((char)reader.read());
- }
- }
- } else {
- while (peek() != '<') {
- sb.append((char)reader.read());
- }
- }
- return sb.toString();
- }
这次使用的peek方法是前面那个从基本的XML文档返回一个字符串序列的peek方法的变体。这个peek变体让语法分析程序判断它将分析的文本是否被装入一个CDATA块。compareIntArrays函数是一个执行两个整数数组的深度比较的简单程序。