设为首页 收藏本站
查看: 872|回复: 0

[经验分享] SharePoint内容定制之XSLT高级用法——使用Muenchian方法分组XML数据

[复制链接]

尚未签到

发表于 2015-9-28 01:17:12 | 显示全部楼层 |阅读模式
  分组在XSLT处理中是一个很常见的问题,怎样才能将一系列XML节点元素组织到不同的分组里?最常见的情况是处理从数据库中得到的XML输出,数据库通常是根据数据表中的记录生成结果。例如,一个地址簿可能输出下面的内容:




<records>
    <contact id="0001">
        <title>Mr</title>
        <forename>John</forename>
        <surname>Smith</surname>
    </contact>
    <contact id="0002">
        <title>Dr</title>
        <forename>Amy</forename>
        <surname>Jones</surname>
    </contact>
    ...
</records>

  
  
  现在的问题是怎样把这段文本转换成多个按照surname来分组的列表,例如:
  




Jones,<br />
Amy (Dr)<br />
Brian (Mr)<br />
Smith,<br />
Fiona (Ms)<br />
John (Mr)<br />

  
  
  
  
  通过以下两个步骤可实现这个需求:


  • 找出都有哪些surname。
  • 获取具有相同surname值的所有contact节点。
  
  要找出都有哪些surname就要先找出每个surname对应的第一个contact节点,一个方法就是找出那些surname与先前节点的surname都不同的的contact节点。




contact[not(surname = preceding-sibling::contact/surname)]
  
  
  一旦这些contact节点被找出,就很容易找出它们对应的surname了,然后在此基础上再找出具有相同surname的所有contact节点。
  




<xsl:apply-templates select="/records/contact[surname = current()/surname]" />
  
  
  
  但是对于那些比较大的XML数据(比如海量数据库),这种方法也存在缺点,它使用了两个XPath查询进行了大量的处理。使用preceding-siblings遍历所有前驱兄弟节点会花费大量的时间,尤其是当前节点处于尾部的时候。同样地,查找所有具有某个指定surname的contact节点也会遍历所有contact节点。这种做法效率是很低的。
  
  Muenchian是由Steve Muench开发的一种分组方法,它通过keys更高效的实现这种需求。Keys通过分配一个key值给一个节点,然后就可以简单的通过key值来访问节点。如果存在多个节点有相同的key值,那么通过这个key值就可以取到所有这些节点。这意味着,如果你想根据节点的某个属性对一组节点进行高效分组时,可以使用keys。
  
  再回到上面的例子,我们想通过surname来对所有的contact节点分组,于是就创建一个key,并且给每个contact节点一个key值(也就是surname值)。需要分组的节点匹配match属性指定的表达式,key值通过use属性的表达式指定,如下:
  




<xsl:key name="contacts-by-surname" match="contact" use="surname" />
  
  
  
  在key定义好以后,如果知道了surname,我们便可快速查找到相应的contact节点,例如下面的表达式将给出所有surname为Smith的contact节点。
  




key('contacts-by-surname', 'Smith')
  
  
  
  然后这就可以很容易实现上面提到的第二个步骤。
  




<xsl:apply-templates select="key('contacts-by-surname', surname)" />
  
  
  
  不过,我们首先需要做的是找出都有哪些surname,同时找出具有某个surname的第一个contact节点。在这里我们可以再次使用keys。当我们把surname作为key的时候,contact节点就已经是这个集合的一部分了,但它是否是集合中的第一个元素呢(按照XML文档顺序)?还是在排在后面?我们仅仅关心集合中的第一个元素。
  
  要找出一个contact节点是否为由key筛选出的结果中的第一个元素,就要把contact和由key筛选出的结果中的第一个元素作比较。有很多常用的方法可以用来判断两个节点是不是同一个节点:
  1. 比较通过generate-id()函数生成的唯一标识符。
  




contact[generate-id() = generate-id(key('contacts-by-surname', surname)[1])]
  
  
  2. 检查由这两个节点组成的新集合内部有一个还是两个节点——因为同一个节点在节点集合中不可能出现两次,所以如果这个集合中只有一个元素,那么这之前提到的两个节点肯定就是同一个节点。
  




contact[count(. | key('contacts-by-surname', surname)[1]) = 1]
  
  
  
  在找出所有的组以后,可以按照需求对它们排序。同样,组内的节点也可以进行排序。最终,利用下面的这个template,我们就可以分组输出从数据中取到的XML信息。
  




<xsl:key name="contacts-by-surname" match="contact" use="surname" />
<xsl:template match="records">
    <xsl:for-each select="contact[count(. | key('contacts-by-surname', surname)[1]) = 1]">
        <xsl:sort select="surname" />
        <xsl:value-of select="surname" />,<br />
        <xsl:for-each select="key('contacts-by-surname', surname)">
            <xsl:sort select="forename" />
            <xsl:value-of select="forename" /> (<xsl:value-of select="title" />)<br />
        </xsl:for-each>
    </xsl:for-each>
</xsl:template>

  
  
  
  通常,Muenchian是最好的节点分组方法,因为它不需要遍历大量的节点,所以更高效。这种方法特别适用于处理从数据库中获取到的表结构数据,例如以某种层级关系重新组织这些从数据库中得到的数据。它也适用于任何情况下利用XPath可访问到的节点属性对节点集合进行分组。
  
  Muenchian有一个缺点,它只能在支持keys的XSLT处理器下使用。这就排除了James Clark的xt还有2000年5月以前发布的MSXML。另外,使用keys也是相当消耗内存资源的,因为所有的节点和key值都必须保存在内存中。最后,在多个XML文档之间使用keys进行分组也是一项比较复杂的工作。
  
  
  相关链接:
  XSLT Recommendation: Keys
  XSLT Recommendation: generate-id()
  
  
  [原文地址:http://www.jenitennison.com/xslt/grouping/muenchian.html]
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-119619-1-1.html 上篇帖子: 提升SharePoint代码的权限 下篇帖子: Changing SharePoint 2010 default font size
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表