2

我想构建一个 XML 文件作为数据存储。它应该看起来像这样:

<datastore>
    <item>
        <subitem></subitem>
        ...
        <subitem></subitem>
    </item>
    ....
    <item>
        <subitem></subitem>
        ...
        <subitem></subitem>
    </item>
</datastore>

在运行时,我可能需要将项目添加到数据存储区。项目的数量可能很高,因此我不想将整个文档保存在内存中并且不能使用 DOM。我只想写发生变化的部分。还是 DOM 支持这个?

我第一次看 StAX,但我不确定它是否符合我的要求。

在根元素关闭之前记住文件末尾的光标位置不是最好的吗?这始终是添加新项目的位置。因此,如果我记得那个位置并在更改期间保持最新,我可以在最后添加一个新项目,而无需遍历整个文件。

也许第二个游标可以独立于第一个游标使用,以迭代文档仅用于阅读目的。

我看不到 StAX 支持任何这些,是吗?

没有基于块的文件API而不是基于流的API吗?文件和文件系统不是块“设备”的典型示例吗?如果有这样的 API,它对我的​​问题有帮助吗?

提前致谢。

4

4 回答 4

1

更新 XML 基本上是不可能的,因为没有“便宜”的方式来插入数据。

附加 XML 并不是那么糟糕。您需要做的就是寻找文件的末尾,然后返回“结束标记”(在本例中为</datastore>),然后开始写入。总而言之,这是一个便宜的操作,但没有一个框架真正支持这一点,因为它们大多都设计用于处理格式良好、完整的 XML 文档,作为一个整体,而不是碎片。

您可以使用类似 StAX 的东西,但在这种情况下,StAX 不知道 <datastore> 标记,而只是知道 <item> 标记及其元素。然后,您创建 Items 并开始一遍又一遍地写入您已设置的同一 OutputStream。

这是最好的方法。

但是,如果您需要删除或更改数据,那么您需要重写一些东西,或者做一些黑客攻击,例如将元素标记为“非活动”,在 XML 文件中搜索它们,寻找“活动 =”Y”属性,然后就地将 Y 更改为 N。它可以做到,它的效率最高,但它远远超出了正常的 XML 处理框架让你做的事情。如果我这样做,我会阅读整个文件并跟踪这些条目并记下它们在其中的位置,以便以后我可以轻松地有效地查找和更改它们。

然后,当您更新某些内容时,您会“停用”旧的,并“附加”新的。最终通过重写所有文件并丢弃旧的“非活动”条目来对文件进行 GC。

于 2011-01-26T19:22:06.803 回答
1

根据经验,XML 文件作为数据存储的效率不是很高,对于您似乎想要使用它们的基于记录的数据来说不是很有效。

但是,如果您已经拥有该文件并且绝对无法对其执行任何操作,则可以使用 StAX XMLEventReaders 和XMLEventWriters 快速读取文件并在其中插入/修改元素。

但是当我说快速时,我的意思是比 DOM 更快,但远不如任何关系数据库有效。

更新:您可以考虑的另一个选项是vtd-xml,虽然我没有在实际项目中尝试过,但它实际上看起来相当不错。

于 2011-01-26T19:23:22.327 回答
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 数据库可能会更好。但多年来,我一直在使用这种方法来记录撒克逊人的订单,目前文件大小约为 8Mb,而且效果很好。

于 2011-01-26T23:24:55.100 回答
0

部分更新 XML 文件不是很容易或很有效,因此您不会找到对它作为用例的太多支持。

真的,听起来您需要一个合适的数据库,也许需要一个将数据导出为 XML 的工具。

If you don't want to use a DB and insist on storing the data purely as XML you might consider keeping all your items in memory as objects. Whenever a new one is added you can write all of them out to XML. It might seem inefficient, but depending on your data size might still be good enough.

If you choose this path, you might want to check out the Xstream library to make this quite easy, see stream tutorial for a quick example.

于 2011-01-26T23:41:04.323 回答