【问题标题】:Java SAX Parser, storing AttributesJava SAX 解析器,存储属性
【发布时间】:2011-09-14 07:05:54
【问题描述】:

我正在尝试将当前文档位置存储在堆栈中,推入 startElement,弹出 endElement。现在我正在使用:

public void startElement(String namespaceURI, String elname,
                         String qName, Attributes atts) throws SAXException {
    original.append(innerText);
    original.append("<");
    original.append(elname);
    original.append(">");
    docStack.push(new StackElement(elname,atts));
....

不幸的是,当它稍后尝试读取 atts 时,它会给出错误: 原因:java.lang.IllegalStateException:属性只能在startElement()的范围内使用。

是否有任何快速、可靠的方式来存储属性? 另外,有没有比为每个开始标签构造一个新的自定义对象 StackElement 更好的方法?

【问题讨论】:

    标签: java xml sax


    【解决方案1】:

    当您将 Attributes 推送到您的自定义对象堆栈时,您将获取实际的 Attributes 对象,根据documentation 的说法是这样的:

    atts - 附加到元素的属性。如果没有属性,它应该是一个空的 Attributes 对象。 startElement返回后这个对象的值是未定义的(强调我的)

    您应该改为在您的 startElement(...) 方法中捕获 Map 中的属性。这样您就可以随时随地使用它们。

    【讨论】:

    • 使用每个 startElement 构造对象似乎会有点慢,但即使有这个开销,它仍然应该比 DOM 更有效,对吧?
    • 它肯定会比 DOM 更有效,因为您不会存储所有内容,只是存储一些内容。我认为您对对象创建的担忧是没有根据的,因为 Java 不是一种缓慢而笨重的语言。无论如何,一旦你完成解析,内存和对象将被清理。
    • 这个真的能咬到你。我有一个包含 500M 的文档,但它在中间的某个地方失败了(经过 10 多分钟的处理)。我只是在缓存属性对象以在 endElement 函数中使用(因为我的模型对象需要元素文本和属性)。事实证明它有效......有一段时间......猜猜阅读细则很重要。
    • 除了Map,您还可以使用org.xml.sax.helpers.AttributesImpl,它的构造函数采用Attributes 对象。开销可能相似。
    【解决方案2】:

    如果Attributes 是上下文相关的,请在StackElement 构造函数中从它们中提取您需要的内容(并且不要存储引用)。

    这样的事情会做:

    public class StackElement {
    
        private Map<String, String> map = new HashMap<String, String>();
    
        public StackElement(String elname, Attributes atts) {
    
            for (int i = 0; i <  atts.getLength(); i++) {
                map.put(atts.getQName(i),atts.getValue(i));
            }
        }
    }
    

    附言看起来我抄袭了@nicholas 的答案,但老实说,我已经把它打出来了,并且在他发布时正在处理代码。

    【讨论】:

    • 我曾想过将所有内容复制到这样的地图中,但我认为这可能效率低下,尤其是因为我不需要每个元素上的所有属性。那会更慢,因为它要构造两个新类,构造一个新的 StackElement 和 HashMap,并在每个元素上查询所有属性!我的问题是,有没有更有效的方法来做到这一点,也许“冻结”属性并添加到 StackElement?
    • 那个getQName应该是getLocalName
    猜你喜欢
    • 1970-01-01
    • 2013-03-16
    • 2014-03-16
    • 2015-06-18
    • 2015-09-28
    • 2015-02-15
    • 2017-08-19
    • 1970-01-01
    • 2012-01-25
    相关资源
    最近更新 更多