如何使用Stack数据结构逐段解析XML文件并校验标签合法性
报错原因排查
- 核心报错触发原因:Config类的循环逻辑中,单次循环内多次调用
nextLine()方法,hasNextLine()仅在循环开始前校验一次存在行,后续多次调用nextLine()会消耗掉所有行内容,无剩余行时就会抛出NoSuchElementException。 - 逻辑设计错误1:XML所有内容都在同一行,按行读取的整段内容无法直接和单个标签匹配,判断条件永远不会命中。
- 逻辑设计错误2:字符串相等判断使用
==而非equals()方法,Java中==对比字符串对象内存地址,而非内容值,即使内容匹配也会返回false。 - 逻辑设计错误3:未区分开始标签、结束标签,直接else就执行
pop(),没有校验栈是否为空就弹出,遇到非法标签时会触发空栈异常。 - 冗余问题:Config构造方法传入的文件名参数没有被使用,内部硬编码了文件路径。
修正后实现方案
实现逻辑
- 一次性读取XML文件的全部内容
- 提取所有
<>包裹的标签,区分开始标签(不带/)和结束标签(带/) - 遇到开始标签压入栈,遇到结束标签时校验栈顶是否为对应的开始标签,匹配则弹出
- 全部标签处理完成后栈为空则输出valid,否则为invalid
修正后代码
Config类
import java.util.HashMap; import java.util.Stack; import java.util.Scanner; import java.io.File; import java.io.FileNotFoundException; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Config { HashMap<String, String> obj = new HashMap<>(); Stack<String> tagStack = new Stack<>(); // 匹配XML标签的正则 private static final Pattern TAG_PATTERN = Pattern.compile("<[^>]+>"); public Config(String name) { try { File xmlFile = new File(name); Scanner reader = new Scanner(xmlFile); // 读取全部XML内容 StringBuilder xmlContent = new StringBuilder(); while (reader.hasNextLine()) { xmlContent.append(reader.nextLine()); } reader.close(); // 提取所有标签 Matcher matcher = TAG_PATTERN.matcher(xmlContent.toString()); boolean isValid = true; while (matcher.find()) { String tag = matcher.group(); // 判断是否是结束标签 if (tag.startsWith("</")) { String startTag = tag.replace("/", ""); // 栈为空或者栈顶不匹配则非法 if (tagStack.isEmpty() || !tagStack.peek().equals(startTag)) { isValid = false; break; } tagStack.pop(); } else { // 开始标签压入栈 tagStack.push(tag); } } // 全部处理完成后栈为空且过程无异常则合法 if (isValid && tagStack.isEmpty()) { System.out.println("valid"); } else { System.out.println("invalid"); } } catch (FileNotFoundException e) { System.out.println("An error occurred."); e.printStackTrace(); } } }
Main类(仅修正冗余逻辑,原有读取atm.log的逻辑保留)
import java.io.File; import java.io.FileNotFoundException; import java.util.Scanner; public class Main { public static void main(String[] args) throws Exception { try { File logFile = new File("atm.log"); Scanner logReader = new Scanner(logFile); while (logReader.hasNextLine()) { String data = logReader.nextLine(); System.out.println(data); } logReader.close(); } catch (FileNotFoundException e) { System.out.println("An error occurred when reading atm.log."); e.printStackTrace(); } String xmlName = "atm.xml"; Config info = new Config(xmlName); } }
内容的提问来源于stack exchange,提问作者Matt Beagle
相关产品推荐
相关产品推荐

