下面是我正在处理的问题的简化版本:我有一堆xml数据,用于编码有关人员的信息。每个人都有唯一的'id'属性,但他们可能会有很多名字。例如,在一个文档中,我可能会发现编写更高效的xquery代码(避免冗余迭代)
而在另一个我可能会发现:
<person id=1>Sir Paul McCartney</person>
<person id=2>Richard Starkey</person>
我想使用XQuery产生一个新文档,列出与给定ID相关联的每一个名字。即:
<person id=1>
<name>Paul McCartney</name>
<name>Sir Paul McCartney</name>
<name>James Paul McCartney</name>
</person>
<person id=2>
...
</person>
我在XQuery目前这样做的方式是这样的(伪代码式的):
let $ids := distinct-terms([all the id attributes on people])
for $id in $ids
return <person id={$id}>
{
for $unique-name in distinct-values
(
for $name in ([all names])
where $name/@id=$id
return $name
)
return <name>{$unique-name}</name>
}
</person>
的问题是,这实在是太慢了。我想象的瓶颈是最内层的循环,每个id(其中大约有1200个)会执行一次。我正在处理一些公平的数据(300 MB,分布在大约800个xml文件中),因此即使在内部循环中执行一次查询也需要大约12秒,这意味着重复1200次需要大约4次小时(这可能是乐观的 - 该过程至今已经运行了3个小时)。它不仅速度慢,而且使用了大量的虚拟内存。我使用的是Saxon,为了避免出现内存错误,我必须将java的最大堆大小设置为10 GB(!),并且它目前使用6 GB的物理内存。
因此,这里就是我真的很想这样做(在Python化伪代码):
persons = {}
for id in ids:
person[id] = set()
for person in all_the_people_in_my_xml_document:
persons[person.id].add(person.name)
在那里,我只是做了它的线性时间,只有一次扫描的XML文档。现在,有没有办法在xquery中做类似的事情?当然,如果我能想象得到它,一种合理的编程语言应该能够做到这一点(他说,混沌地说)。我想这个问题是,与Python不同,xquery没有(据我所知)具有像关联数组一样的东西。
有没有一些聪明的方法呢?如果不这样做,是否有什么比我用来实现目标的xquery更好?因为真的,我投掷在这个相对简单的问题上的计算资源有点荒谬。
我觉得同样的事情使用VTD-XML和XPath可以更快地完成,这是否会成为您考虑的选项? – 2010-05-13 02:40:03
好问题(+1)。查看我的答案以获得简单高效的XSLT 2.0解决方案。 – 2010-09-04 17:11:16