Java中XML注释与处理指令的检测/移除及冗余空格去除方案
Java中高效处理XML注释与处理指令的两种场景方案
场景一:检测到注释/处理指令则终止处理,否则移除冗余空格
要实现这个需求,最高效的方式是采用SAX流式解析——它不需要加载整个XML到内存,适合处理大文件,且能在解析过程中实时检测注释和处理指令。
1. 实现检测逻辑
自定义SAX处理器,重写注释和处理指令的回调方法,一旦触发就抛出异常终止处理:
import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public class XmlValidationHandler extends DefaultHandler { // 检测到注释则抛出异常 @Override public void comment(char[] ch, int start, int length) throws SAXException { throw new SAXException("XML包含注释,处理终止"); } // 检测到处理指令则抛出异常 @Override public void processingInstruction(String target, String data) throws SAXException { throw new SAXException("XML包含处理指令,处理终止"); } }
2. 执行检测
通过SAXParser加载自定义处理器完成验证:
import org.xml.sax.SAXException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import java.io.File; public class XmlValidator { public static void validateNoCommentsOrPIs(File xmlFile) throws Exception { SAXParserFactory factory = SAXParserFactory.newInstance(); factory.setNamespaceAware(true); SAXParser parser = factory.newSAXParser(); parser.parse(xmlFile, new XmlValidationHandler()); } }
3. 验证通过后移除冗余空格
使用JDK自带的Transformer完成空格压缩,仅保留文本内容中必要的空格:
import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import java.io.File; public class XmlSpaceCompressor { public static void compressRedundantSpaces(File input, File output) throws Exception { TransformerFactory factory = TransformerFactory.newInstance(); Transformer transformer = factory.newTransformer(); // 关闭缩进,移除冗余空格 transformer.setOutputProperty("indent", "no"); transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "0"); transformer.transform(new StreamSource(input), new StreamResult(output)); } }
4. 组合调用
public class Main { public static void main(String[] args) { File input = new File("source.xml"); File output = new File("compressed.xml"); try { // 先执行检测 XmlValidator.validateNoCommentsOrPIs(input); // 检测通过后压缩空格 XmlSpaceCompressor.compressRedundantSpaces(input, output); System.out.println("处理成功"); } catch (SAXException e) { System.err.println("处理失败:" + e.getMessage()); } catch (Exception e) { e.printStackTrace(); } } }
场景二:移除注释与处理指令,同时压缩冗余空格
同样采用SAX流式解析,在解析过程中跳过注释和处理指令,同时构建清理后的XML文档,全程无需加载完整XML,效率最优。
1. 实现清理逻辑
自定义SAX处理器,结合TransformerHandler直接输出清理后的XML,跳过注释和处理指令,同时压缩文本中的冗余空格:
import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.sax.SAXTransformerFactory; import javax.xml.transform.sax.TransformerHandler; import javax.xml.transform.stream.StreamResult; public class XmlCleanerHandler extends DefaultHandler { private TransformerHandler transformerHandler; public XmlCleanerHandler(StreamResult result) throws Exception { SAXTransformerFactory factory = (SAXTransformerFactory) TransformerFactory.newInstance(); transformerHandler = factory.newTransformerHandler(); Transformer transformer = transformerHandler.getTransformer(); // 关闭缩进,压缩空格 transformer.setOutputProperty("indent", "no"); transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "0"); transformerHandler.setResult(result); transformerHandler.startDocument(); } // 转发元素开始事件 @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { transformerHandler.startElement(uri, localName, qName, attributes); } // 转发元素结束事件 @Override public void endElement(String uri, String localName, String qName) throws SAXException { transformerHandler.endElement(uri, localName, qName); } // 压缩文本中的冗余空格,仅保留非空文本 @Override public void characters(char[] ch, int start, int length) throws SAXException { String text = new String(ch, start, length).trim(); if (!text.isEmpty()) { transformerHandler.characters(text.toCharArray(), 0, text.length()); } } // 跳过注释 @Override public void comment(char[] ch, int start, int length) throws SAXException { // 无操作,直接跳过 } // 跳过处理指令 @Override public void processingInstruction(String target, String data) throws SAXException { // 无操作,直接跳过 } // 结束文档 @Override public void endDocument() throws SAXException { transformerHandler.endDocument(); } }
2. 执行清理
import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import javax.xml.transform.stream.StreamResult; import java.io.File; import java.io.FileOutputStream; public class XmlCleaner { public static void cleanXml(File input, File output) throws Exception { SAXParserFactory factory = SAXParserFactory.newInstance(); factory.setNamespaceAware(true); SAXParser parser = factory.newSAXParser(); try (FileOutputStream fos = new FileOutputStream(output)) { StreamResult result = new StreamResult(fos); XmlCleanerHandler handler = new XmlCleanerHandler(result); parser.parse(input, handler); } } }
3. 调用示例
public class Main { public static void main(String[] args) { File input = new File("source.xml"); File output = new File("cleaned.xml"); try { XmlCleaner.cleanXml(input, output); System.out.println("XML清理完成"); } catch (Exception e) { e.printStackTrace(); } } }
内容的提问来源于stack exchange,提问作者Hans Wurst
相关产品推荐
相关产品推荐

