XMLStreamReader.getLocation()返回意外字符偏移量的原因咨询
XMLStreamReader获取的CharacterOffset不符合预期及解决方案
问题重现
测试代码
import javax.xml.stream.XMLInputFactory; import java.io.ByteArrayInputStream; import java.nio.charset.StandardCharsets; class Scratch { public static void main(String[] args) throws Exception { var document = "<foo>bar</foo>"; try (var is = new ByteArrayInputStream(document.getBytes(StandardCharsets.UTF_8))) { var reader = XMLInputFactory.newInstance().createXMLStreamReader(is); System.out.println(reader.getLocation()); } } }
预期输出
Line number = 1 Column number = 1 System Id = null Public Id = null Location Uri= null CharacterOffset = 0
实际输出
Line number = 1 Column number = 1 System Id = null Public Id = null Location Uri= null CharacterOffset = 4
补充信息
- 无论根元素是
<foo还是<foobar,CharacterOffset始终为4 - 运行环境:Zulu JDK 17,使用com.sun.org.apache.xerces的XMLStreamReader实现
- 需求:需要获取XML元素/标签的可靠位置信息,用于后续DataBuffer切片操作
原因分析
出现CharacterOffset=4的原因是Xerces解析器在初始化阶段会预读前4个字符,尝试检测是否存在XML声明(格式为<?xml)。即使你的XML文档没有XML声明,解析器也会完成这个预读检查,导致此时返回的偏移量指向预读后的位置,而非文档起始点。
解决方案:获取元素的可靠位置
要获取XML元素的准确位置,不能在刚创建XMLStreamReader时直接调用getLocation(),而是需要遍历XML事件,当触发START_ELEMENT事件时再获取位置,此时的位置才对应元素标签的实际起始位置。
修改后的示例代码:
import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamConstants; import java.io.ByteArrayInputStream; import java.nio.charset.StandardCharsets; class Scratch { public static void main(String[] args) throws Exception { var document = "<foo>bar</foo>"; try (var is = new ByteArrayInputStream(document.getBytes(StandardCharsets.UTF_8))) { var reader = XMLInputFactory.newInstance().createXMLStreamReader(is); // 遍历XML事件,找到START_ELEMENT事件 while (reader.hasNext()) { int eventType = reader.next(); if (eventType == XMLStreamConstants.START_ELEMENT) { // 此时获取的位置是元素标签的实际起始位置 System.out.println(reader.getLocation()); break; } } } } }
运行这段代码后,会输出符合预期的CharacterOffset=0,对应根元素<foo>的起始位置。
内容的提问来源于stack exchange,提问作者PeterMue
相关产品推荐
相关产品推荐

