以文本方式查看主题 - 中文XML论坛 - 专业的XML技术讨论区 (http://bbs.xml.org.cn/index.asp) -- 『 XSL/XSLT/XSL-FO/CSS 』 (http://bbs.xml.org.cn/list.asp?boardid=8) ---- [原创翻译]XSLT MUENCHIAN分组法 (http://bbs.xml.org.cn/dispbbs.asp?boardid=8&rootid=&id=70693) |
-- 作者:宇义 -- 发布时间:12/19/2008 11:59:00 AM -- [原创翻译]XSLT MUENCHIAN分组法 原文:http://www.jenitennison.com/xslt/grouping/muenchian.xml 在XSLT中分组是一个常见问题:如何将一组元素排列成组?一种最常见的情况就是将数据库中的数据通过XML进行输出。通常数据库返回的XML结构是与数据库中的记录一样的。例如一个地址簿,它可能会给你如下XML: <records> 问题是如何将这个平坦的输入变成一个通过surname分组的列表,输出成如下格式: Jones,<br /> 这个解决方案分两步: 1. 不重复的找出所有surname; 要不重复的找出contact中出现的所有surname,可以找surname的第一次出现。方法是找到那些在前面所有的contact中的surname是没有出现过的contact: contact[not(surname = preceding-sibling::contact/surname)] 当这些contact已经被确定,找到等于它的surname就很容易了,方法是找到所有的等于当前surname的contact: <xsl:apply-templates select="/records/contact[surname = current()/surname]" /> 这种方法的最大问题在一个很大的XML文件中这两个XPath将使用过多的处理时间(比如它们来自于一个大数据库)。在XML中通过 “preceding-siblings”搜索所有的前置兄弟节点轴越后面的元素会越慢。类似的,每次找所有等于一个确定的surname的 contact将会遍历所有的contact节点,这使得它非常效率低下。 Muenchian方法是Steve Muench通过使用更快速的key方法提高分组功能的效率而开发的一种方法。key给一个节点分配一个key值,您便可以通过key值方便的获得那个节点。如果有很多节点使用同一个key值,那么当你使用key值时那些所有的节点也都会被检索到。这意味着如果你想要将一组节点通过它们的某一个属性进行分组,你可以使用key将它们进行分组。 我们还是用上面的地址簿例子。我们希望通过将contact通过它们的surname分组,于是我们建立一个key,分配给所有的contact一个来自于它的surname的key值。我们希望分组的节点应该在“match”属性中进行匹配。我们想要使用的key值通过“use”属性指定: <xsl:key name="contacts-by-surname" match="contact" use="surname" /> 通过定义这个key,如果我们知道一个surname,就可以快速的获得所有的等于那个surname的contact。比如: key('contacts-by-surname', 'Smith') 将返回所有surname为“Smith”的contact。所以它很容易的满足了上面所提到的第二个步骤(取得所有相同surname的contact): <xsl:apply-templates select="key('contacts-by-surname', surname)" /> 我们需要解决的第一个步骤是确定这个XML中包含了哪些surname,这涉及到确定第一个contact出现在XML中的surname。这里我们可以再次使用key。我们已经知道当我们将surname作为key的时候contact是一组节点的一部分:问题是它是那组节点中的第一次出现(按照文档中的节点排序)还是第n次出现?我们仅仅需要数据中的第一次出现。 比较当前contact是否是等于当前contact的surname的所有contact中的第一个。有两种通用的方法可以测试两个节点是否相同: 1. 比较两个节点唯一的生成标实(使用generate-id()): contact[generate-id() = 2. 看节点集中是一个节点还是两个节点组成的——节点集不能包含相同的节点,所有节点集中如果只有一个节点,那么它们一定是相同的: contact[count(. | key('contacts-by-surname', surname)[1]) = 1] 当你已经确定了分组,你可以用任意的顺序排列它们。类似的,你可以在分组中任意的排列节点。下面是一个模板,它建立了我们指定的从数据库中取得的XML的输出: <xsl:key name="contacts-by-surname" match="contact" use="surname" /> Muenchian方法是通常情况下用来从XML源节点分组并输出的最好的方法,因为它并没有遍历很多的节点,因此它的效率更高。尤其是它特别适合当你有一个从数据库中取得的平坦的XML输出的情况,比如你需要结构成等级。它适用于很多情况比如当你需要通过使用XPath检索某个元素的属性将节点机进行分组时。 不足的是Muenchian方法只能工作在支持key的XSLT处理器中。在James Clark的xt和2000年6月之前的MSXML版本中不能使用。并且使用key将会占用相当多的内存,因为所有的节点集和它们的key值将会存储在内存中。最后,当需要分组的节点来自不同的文档时,使用key会相当麻烦。 |
-- 作者:Qr -- 发布时间:12/19/2008 1:07:00 PM -- 不错,谢谢。
|
-- 作者:hexun831012 -- 发布时间:12/19/2008 9:46:00 PM -- 不错,宇义老兄又出现了,每次都有惊喜 说点个人意见,还是那句老话,XSL被设计用来处理结构,而不是结构里的数据,所以分组对XSL来说,并不怎么适合 个人有的想法,如果实在需要通过XSL进行分组,以我个人的经验,2次转换是最好的方式 |
-- 作者:宇义 -- 发布时间:12/21/2008 12:22:00 AM -- 两次转换什么概念?可以举个例子吗? XSLT2.0内置了分组功能,for-each-group。 |
W 3 C h i n a ( since 2003 ) 旗 下 站 点 苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》 |
51.758ms |