【发布时间】:2016-12-02 12:35:30
【问题描述】:
我有以下两级XML 结构。一个盒子列表,每个盒子都包含一个抽屉列表。
<Boxes>
<Box id="0">
<Drawers>
<Drawer id="0"/>
<Drawer id="1"/>
...
</Drawers>
</Box>
<Box id="1">
...
</Box>
</Boxes>
我正在使用StAX 解析它并通过两个Iterators 暴露结构:
BoxIterator implements Iterator<Box>, Iterable<Box>Box implements Iterable<Drawer>DrawerIterator implements Iterator<Drawer>
然后我可以执行以下操作:
BoxIterator boxList;
for (Box box : boxList) {
for (Drawer drawer : box) {
drawer.getId()
}
}
在Iterators 的底层,我使用的是StAX,它们都在访问相同的底层XMLStreamReader。如果我调用BoxIterator.next(),它将影响后续调用DrawerIterator.next() 时返回的结果,因为光标将移动到下一个框。
这会破坏Iterator 的合同吗?
有没有更好的方法来使用StAX 迭代两级结构?
【问题讨论】:
-
您的描述看起来像
Box.iterator返回一个新的DrawerIterator,如果是这样,合同就不会被破坏,因为DrawerIterator无论如何都应该只返回当前框内的元素。 -
@Thomas
Box.iterator()将在每次调用时返回相同的DrawerIterator,因为无论如何它们都将访问相同的底层流。这意味着即使是过去调用Box.iterator()返回的DrawerIterator也会神奇地提前。所有人都将始终在相同的光标位置访问基础流。 -
啊,我明白了。那会破坏合同。您是否需要在每次调用时返回相同的实例?如果您每次都返回一个新实例并按顺序迭代(即没有随机访问),那么光标位置是否会被提前并不重要。在您遍历一个盒子的抽屉后,对该盒子的任何进一步调用 DrawerIterator 的
hasNext()应该返回 false。 -
@Thomas 我想这是可能的,尽管它需要一些簿记。在实践中,我只想以理智的方式使用它,所以我不知道是否值得做预防病理病例的工作。另一方面,我想应该有更好的模式。我正在考虑只做一个
DrawerIterator,它会有一个currentBox字段,会自动更新。然而,这仍然存在一个问题,即所有迭代器都将访问相同的底层流,因此推进一个,将推进所有其他迭代器。 -
@Roland:你想达到什么目的?您只对
Drawerids 或Drawers感兴趣吗?您对Boxid 不感兴趣吗?也许你可以用另一种方式使用 StAX。 StAX 可以在找到元素的开头或结尾时解析文件并生成事件。您所要做的就是检查该元素是Box还是Drawer。