Java解析含<?..?>标记的XML:获取TAG值及标记含义咨询
关于XML处理指令()的说明及TAG值获取方案
嗨,咱们一步步来解决你的问题:
一、XML中标记的用途
你看到的<?TAGS?>、<?TAG 024?>、<?END-TAGS?>都是XML处理指令(Processing Instruction,简称PI),它的作用是给处理这份XML的应用程序传递特定指令或元数据,不属于标准的XML元素/属性范畴。
PI的语法是<?目标名 [指令数据]?>,其中:
目标名(比如这里的TAGS、TAG、END-TAGS)告诉处理程序这是什么类型的指令- 后面的可选
指令数据是传递给处理程序的具体信息(比如<?TAG 024?>里的024)
这类标记不是XML的核心数据结构,所以JAXB这类专注于映射XML元素/属性到Java对象的框架,默认不会处理它们——这也是你用JAXB注解拿不到这些值的原因。
二、获取块内的所有TAG值的方法
因为JAXB默认不支持PI处理,我们需要结合底层XML解析器(DOM/SAX/StAX)来实现,下面给你两种常用方案:
方案1:使用DOM解析器
DOM会把整个XML文档加载到内存中,你可以遍历节点找到所有PI,然后筛选出TAG类型的PI并提取数据:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(new InputSource(new StringReader(xmlContent))); // 遍历文档中的所有节点 NodeList nodeList = doc.getChildNodes(); for (int i = 0; i < nodeList.getLength(); i++) { Node node = nodeList.item(i); if (node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) { ProcessingInstruction pi = (ProcessingInstruction) node; String target = pi.getTarget(); String data = pi.getData(); // 筛选出TAG类型的PI,提取值 if ("TAG".equals(target)) { System.out.println("TAG值:" + data.trim()); // 这里会输出024 } } }
方案2:使用SAX解析器(内存更友好,适合大文档)
SAX是流式解析,你可以重写processingInstruction方法来捕获所有PI:
SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newSAXParser(); parser.parse(new InputSource(new StringReader(xmlContent)), new DefaultHandler() { private boolean inTagsBlock = false; @Override public void processingInstruction(String target, String data) throws SAXException { super.processingInstruction(target, data); if ("TAGS".equals(target)) { inTagsBlock = true; } else if ("END-TAGS".equals(target)) { inTagsBlock = false; } else if (inTagsBlock && "TAG".equals(target)) { System.out.println("TAG值:" + data.trim()); // 输出024 } } });
结合JAXB的处理方式
如果一定要用JAXB,你可以通过SAXSource把SAX解析和JAXB绑定结合起来:
- 先自定义SAX处理器捕获PI中的TAG值,存储起来
- 然后在JAXB unmarshal的过程中,把这些值注入到对应的Java对象中
举个简化的例子:
// 自定义SAX处理器,保存TAG值 class TagCapturingHandler extends DefaultHandler { private List<String> tagValues = new ArrayList<>(); private boolean inTagsBlock = false; @Override public void processingInstruction(String target, String data) throws SAXException { if ("TAGS".equals(target)) { inTagsBlock = true; } else if ("END-TAGS".equals(target)) { inTagsBlock = false; } else if (inTagsBlock && "TAG".equals(target)) { tagValues.add(data.trim()); } } public List<String> getTagValues() { return tagValues; } } // 结合JAXB使用 TagCapturingHandler handler = new TagCapturingHandler(); XMLReader reader = XMLReaderFactory.createXMLReader(); reader.setContentHandler(handler); SAXSource source = new SAXSource(reader, new InputSource(new StringReader(xmlContent))); JAXBContext context = JAXBContext.newInstance(Row.class); Unmarshaller unmarshaller = context.createUnmarshaller(); Row row = (Row) unmarshaller.unmarshal(source); // 把捕获的TAG值设置到Row对象中 row.setTagValues(handler.getTagValues());
这样就能在保留JAXB对象映射的同时,获取到PI中的TAG值了。
内容的提问来源于stack exchange,提问作者Vergie Ericson T.
相关产品推荐
相关产品推荐

