【问题标题】:SAX: How to get the content of an elementSAX:如何获取元素的内容
【发布时间】:2011-05-06 09:55:45
【问题描述】:

我在理解使用 SAX 解析 XML 结构时遇到了一些麻烦。假设有以下 XML:

<root>
  <element1>Value1</element1>
  <element2>Value2</element2>
</root>

还有一个字符串变量myString。

只需使用 startElement、endElement() 和 characters() 方法就可以了。但我不明白如何实现以下目标:

如果当前元素等于element1,则将其值value1 存储在myString 中。据我了解,没有类似的东西:

if (qName.equals("element1")) myString = qName.getValue();

我想我只是想得太复杂了:-)

罗伯特

【问题讨论】:

    标签: java xml sax


    【解决方案1】:

    此解决方案适用于具有文本内容的单个元素。当 element1 有更多的子元素时,需要做更多的工作。布赖恩的话非常重要。 当您有多个元素或想要更通用的解决方案时,这可能会对您有所帮助。我用一个 300+MB 的 xml 文件对其进行了测试,它仍然非常快:

    final StringBuilder builder=new StringBuilder();
    XMLReader saxXmlReader = XMLReaderFactory.createXMLReader();
    
    DefaultHandler handler = new DefaultHandler() {
        boolean isParsing = false;
    
        public void startElement(String uri, String localName, String qName, Attributes attributes) {
            if ("element1".equals(localName)) {
                isParsing = true;
            }
            if (isParsing) {
                builder.append("<" + qName + ">");
            }
        }
    
        @Override
        public void characters(char[] chars, int i, int i1) throws SAXException {
            if (isParsing) {
                builder.append(new String(chars, i, i1));
            }
        }
    
        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
            if (isParsing) {
                builder.append("</" + qName + ">");
            }
            if ("element1".equals(localName)) {
                isParsing = false;
            }
        }
    };
    
    saxXmlReader.setContentHandler(handler);
    saxXmlReader.setErrorHandler(handler);
    
    saxXmlReader.parse(new InputSource(new FileInputStream(input)));
    

    【讨论】:

      【解决方案2】:

      使用 SAX,您需要维护自己的堆栈。对于非常基本的处理,您可以执行以下操作:

      void startElement(...) {
          if (name.equals("element1")) {
              inElement1 = true;
              element1Content = new StringBuffer();
          }
      }
      
      void characters(...) {
          if (inElement1) {
              element1Content.append(characterData);
          }
      }
      
      void endElement(...) {
          if (name.equals("element2")) {
              inElement1 = false;
              processElement1Content(element1Content.toString());
          }
      }
      

      如果您想要示例中的代码,那么您需要使用 DOM 模型而不是 SAX。 DOM 更容易编写代码,但通常比 SAX 更慢且内存成本更高。

      我建议使用第三方库而不是内置的 Java XML 库来进行 DOM 操作。 Dom4J 看起来不错,但可能还有其他库。

      【讨论】:

      • 感谢 Cameron,这正是我所期望的 :-) 由于我的应用程序将在 Android 智能手机上运行,​​我认为使用内置 SAX 解析器比切换到 DOM 更好。
      • 也许使用首选的StringBuilder
      【解决方案3】:

      您应该通过 characters() 记录内容,为每次调用附加到 StringBuilder 并仅在 endElement() 调用时存储连接的值。

      为什么?因为对于元素内容,可以多次调用characters() - 每个调用都引用该文本元素的连续子序列。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-06-11
        • 2013-01-27
        • 1970-01-01
        • 2020-11-07
        • 1970-01-01
        • 2012-11-03
        • 2017-08-03
        相关资源
        最近更新 更多