我想将XML文件构建为数据存储区。看起来应该是这样的:
<datastore>
<item>
<subitem></subitem>
...
<subitem></subitem>
</item>
....
<item>
<subitem></subitem>
...
<subitem></subitem>
</item>
</datastore>
在运行时,我可能需要将项添加到数据存储区。项目数可能很高,因此我不想将整个文档保存在内存中,也不能使用DOM。我只想写一个发生变化的部分。 或DOM是否支持此功能?
我第一次看StAX,但我不确定它是否符合我的要求。
在根元素关闭之前,记住文件末尾的光标位置不是最好的吗?这始终是添加新项目的位置。因此,如果我记得这个位置并在更改期间保持最新,我可以在最后添加一个新项目,而不会遍历整个文件。
也许第二个游标可以从第一个游标中独立使用,只是为了阅读而迭代文档。
我看不出StAX是否支持这一点,是吗?
是否存在基于块的API文件而不是流基础?块文件“设备”不是文件和文件系统的典型示例吗?如果有这样的API,它对我的问题有帮助吗?
提前致谢。
答案 0 :(得分:1)
更新XML基本上是不可能的,因为没有“廉价”的方式来插入数据。
附加XML并不是那么糟糕。你需要做的就是寻找文件的末尾,然后回到“结束标记”(在这种情况下是&lt; / datastore&gt;),然后开始写。这是一个廉价的操作,但是没有一个框架能够真正支持这一点,因为它们主要用于处理格式良好的全船XML文档,整体而言不是碎片。
您可以使用类似StAX的东西,但在这种情况下,StAX不知道&lt; datastore&gt;标签,而不是它只是知道&lt; item&gt;标签及其元素。然后你创建Items并开始一遍又一遍地写入你设置的同一个OutputStream。
这是最好的方法。
但是如果您需要删除或更改数据,那么您可以重写内容,或者做一些黑客行为,例如将元素标记为“非活动”,在XML文件中搜索它们,寻找'active =“Y” '属性,然后就地将Y更改为N.它可以完成,它将大部分都是高效的,但它远远超出普通XML处理框架允许的范围。如果我这样做,我会阅读整个文件并跟踪这些条目并在其中记下它们的位置,以便稍后我可以轻松地有效地寻找和更改它们。
然后,当您更新某些内容时,您将“取消激活”旧内容,并“追加”新内容。最终通过重写所有内容并抛出旧的“非活动”条目来获取GC文件。
答案 1 :(得分:1)
根据经验,XML文件作为数据存储的效率不高,不适用于您似乎想要使用它们的基于记录的数据。
但是如果你已经有了这个文件并且绝对无法做任何事情,你可以使用StAX XMLEventReader
和XMLEventWriter
来快速读取文件并插入/修改元素在它。
但是当我快速说出来时,我的意思是比DOM更快,但远不及任何关系数据库那么有效。
更新:您可以考虑的另一个选项是vtd-xml,虽然我没有在实际项目中尝试过,但它实际上看起来相当不错。
答案 2 :(得分:0)
如果您总是想在最后添加项目,那么处理此问题的最佳方法是拥有两个XML文件。外部的一个datstore.xml只是一个包装器,如下所示:
<!DOCTYPE datastore [
<!ENTITY e SYSTEM "items.xml">
]>
<datastore>&e;</datastore>
文件items.xml如下所示:
<item>....</item>
<item>....</item>
<item>....</item>
没有包装元素。
如果要附加数据,可以打开items.xml并写入其末尾。如果要读取数据,请使用XML解析器打开datastore.xml。
当然,一旦您的数据增长超过20Mb左右,使用XML数据库可能会更好。但是我多年来一直使用这种方法来记录Saxon订单,目前文件大约是8Mb,而且工作正常。
答案 3 :(得分:0)
部分更新XML文件并不是非常简单或有效,因此作为用例,您将不会获得太多支持。
听起来你需要一个合适的数据库,或许还有一个工具可以将数据导出为XML。
如果您不想使用数据库并坚持将数据完全存储为XML,则可以考虑将所有项目作为对象保留在内存中。每当添加新的时,您都可以将所有这些内容写入XML。它似乎效率低下,但根据您的数据大小可能仍然足够好。
如果选择此路径,您可能需要查看Xstream库以使其变得非常简单,请参阅stream tutorial以获取快速示例。