用sax解析器java正确构建xml字符串

3qpi33ja  于 2021-06-29  发布在  Java
关注(0)|答案(1)|浏览(458)

我试图读取一个结构未知的xml文件。这可能是一个文件:

  1. <S:Envelope xmlns:S="http://anamespace">envelopeStart
  2. <S:Body>bodyStart
  3. <ns2:getNextResponse xmlns:ns2="http://anothernamespace">getNextResponseStart
  4. <nextValue>9</nextValue>
  5. getNextResponseEnd</ns2:getNextResponse>
  6. bodyEnd</S:Body>
  7. envelopeEnd</S:Envelope>

这是我实际使用的处理程序:

  1. DefaultHandler handler = new DefaultHandler() {
  2. StringBuilder builder;
  3. Map<String, String> values = new HashMap<String, String>();
  4. @Override
  5. public void startElement(String uri, String localName, String qName,
  6. Attributes attributes) throws SAXException {
  7. builder = new StringBuilder();
  8. }
  9. @Override
  10. public void characters(char ch[], int start, int length) throws SAXException {
  11. builder.append(new String(ch, start, length));
  12. }
  13. @Override
  14. public void endElement(String uti, String localName, String qName) throws SAXException {
  15. values.put(localName, builder.toString());
  16. builder.setLength(0);
  17. }
  18. }

我面临的问题是如果我示例化一个新的 builder 对于每一个被解析的新标签,我都会丢失到现在为止读过的所有开始文本(假设 characters 方法在单个调用中返回所有字符):

  1. new Builder for the Envelope tag
  2. reading characters: envelopeStart
  3. new Builder for the Body tag
  4. reading characters: bodyStart
  5. ...
  6. new Builder for the nextValue tag <- this is the last reference to the builder that I have to use from now on
  7. reading characters: 9
  8. endElement: saving to Map ('nextValue', '9') and resetting length of the last builder instantiated
  9. reading characters: getNextResponseEnd
  10. endElement: saving to Map ('getNextResponse', 'getNextResponseEnd') and resetting length of the last builder instantiated
  11. ...

在这种情况下 values hashmap将具有以下值:

  1. nextValue=9
  2. getNextResponse=getNextResponseEnd (missing getNextResponseStart)
  3. body=bodyEnd (missing bodyStart)
  4. envelope=envelopeEnd (missing envelopeStart)

有没有办法在Map中保存每个标签的开始和结束字符串?

f3temu5u

f3temu5u1#

只需保存一堆StringBuilder:

  1. import org.xml.sax.Attributes;
  2. import org.xml.sax.InputSource;
  3. import org.xml.sax.SAXException;
  4. import org.xml.sax.XMLReader;
  5. import org.xml.sax.helpers.DefaultHandler;
  6. import javax.xml.parsers.ParserConfigurationException;
  7. import javax.xml.parsers.SAXParser;
  8. import javax.xml.parsers.SAXParserFactory;
  9. import java.io.IOException;
  10. import java.io.StringReader;
  11. import java.util.HashMap;
  12. import java.util.Map;
  13. import java.util.Stack;
  14. public class Example {
  15. public static void main(String... args) throws ParserConfigurationException, SAXException, IOException {
  16. Map<String, String> values = new HashMap<String, String>();
  17. DefaultHandler handler = new DefaultHandler() {
  18. Stack<StringBuilder> builders = new Stack<>();
  19. @Override
  20. public void startElement(String uri, String localName, String qName,
  21. Attributes attributes) throws SAXException {
  22. builders.push(new StringBuilder());
  23. }
  24. @Override
  25. public void characters(char ch[], int start, int length) throws SAXException {
  26. builders.peek().append(new String(ch, start, length));
  27. }
  28. @Override
  29. public void endElement(String uti, String localName, String qName) throws SAXException {
  30. values.put(localName, builders.peek().toString());
  31. builders.pop();
  32. }
  33. };
  34. String xml = "<S:Envelope xmlns:S=\"http://anamespace\">envelopeStart\n" +
  35. " <S:Body>bodyStart\n" +
  36. " <ns2:getNextResponse xmlns:ns2=\"http://anothernamespace\">getNextResponseStart\n" +
  37. " <nextValue>9</nextValue>\n" +
  38. " getNextResponseEnd</ns2:getNextResponse>\n" +
  39. " bodyEnd</S:Body>\n" +
  40. "envelopeEnd</S:Envelope>";
  41. SAXParserFactory spf = SAXParserFactory.newInstance();
  42. spf.setNamespaceAware(true);
  43. SAXParser saxParser = spf.newSAXParser();
  44. XMLReader xmlReader = saxParser.getXMLReader();
  45. xmlReader.setContentHandler(handler);
  46. xmlReader.parse(new InputSource(new StringReader(xml)));
  47. }
  48. }
展开查看全部

相关问题