计数XML元素在Android
采取格式化这样一个简单的XML文件:计数XML元素在Android
<Lists>
<List>
<Note/>
...
<Note/>
</List>
<List>
<Note/>
...
<Note/>
</List>
</Lists>
每个节点都有实际保存文件的数据的某些属性。我需要一种非常快速的方法来计算每种元素的数量(列表和注释)。列表仅仅是根,并不重要。
我可以用一个简单的字符串搜索或类似的东西来做到这一点,但我需要尽可能快地做到这一点。
设计参数:
必须在java(Android应用程序)中。
必须AVOID尽可能分配内存。
无论文件中的位置如何,都必须返回文件中Note元素的总数和List元素的数量。
列表数量通常很小(1-4),并且每个文件的笔记数可能非常大(大于1000,通常为100)。
我期待您的建议。
XmlPullParser是流拉XML解析器,当有需要快速有效地处理所有输入要素都应该使用。
你可以尝试这样的事情:
private void pullParserSample(FileInputStream xml) {
int lists = 0;
int notes = 0;
int eventType = -1;
try {
XmlPullParser xpp = XmlPullParserFactory.newInstance().newPullParser();
xpp.setInput(new InputStreamReader(xml));
eventType = xpp.getEventType();
do {
switch (eventType) {
case XmlPullParser.START_TAG:
final String tag = xpp.getName();
if ("Note".equals(tag)) {
notes++;
}
else if ("List".equals(tag)) {
lists++;
}
break;
}
} while ((eventType = xpp.next()) != XmlPullParser.END_DOCUMENT) ;
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.d(TAG, "lists=" + lists + " notes=" + notes);
}
看看实现org.xml.sax.ContentHandler并将其发送到org.xml.sax.XMLReader。
这些类与Android SDK捆绑在一起。这是一种“前向解析器”方法,当文档从开始到结束处理时,涉及ContentHandler的每个XML元素(标签,属性,文本)。正向语法分析器方法在内存使用上很轻松,而且比构建DOM更快。
Sax因为解析所有内容而花费太长时间。我只需要计算节点数量,一个更有效的方法必须在那里。 – CodeFusionMobile 2010-04-06 16:48:13
如果您只是要计算文本中的元素而不是解析文档,您可以依次从文件中读取每行并使用Pattern/Matcher类(我忘记了它)检查该行是否匹配“<Note>
“或”<List>
“,并分别递增计数器。
编辑:另类的想法
通过文件一个字符的时间阅读,当你遇到一个“<”的性格,开始附加所有后续字符是不是一个“>”字符到一个StringBuilder。然后,当你遇到一个“>”符号时,比较StringBuilder字符串到“Note”或“List”或其他什么,并相应地增加计数器。最后,清除StringBuilder并重复,直到文档结束。
你的意思是使用正则表达式?这些在Android上极其昂贵。 – CodeFusionMobile 2010-04-06 17:40:45
不一定需要正则表达式,如果标签是在它们自己的行上,那么你可以修剪行中的空白,并使用String.equals()方法。 – Moonshield 2010-04-06 19:27:44
这些字符串方法需要内存分配,这在移动设计中也很重要。一些内存将被分配,但是如果可能的话,它应该避免具有O(n)关系。 – CodeFusionMobile 2010-04-16 17:41:44
quick dirty未经测试的解决方案,使用生成的状态机Ragel。 把这个喂给ragel,它会为你生成java代码。
生成的代码将使用具有常量内存要求(表和状态变量)的基于表的FSM分析器。它也可以接受部分数据,你可以在任何位置恢复它。
这可能比任何通用解析器或系统的正则表达式都快。 (免责声明:我不是Java程序员,因为它缺少运行所需的框架代码,所以也不是以下任何方式完成的,但是它可能是一个体面的基础。)
%%{
machine nodecounter;
note = '<Note' @{notes++;};
list = '<List' ^'s' @{lists++;};
set = note | list;
main := (set | ^set)*;
}%%
%% write data;
%% write init;
/* */
%% write exec;
这个问题是不是代码高尔夫球,但现实生活中的问题。删除“代码高尔夫”标签。 – 2010-04-06 16:33:16