博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
在XSLT中对for-each语句使用distinct操作
阅读量:7010 次
发布时间:2019-06-28

本文共 4912 字,大约阅读时间需要 16 分钟。

  XSLT用来解析XML文档并按照规定的样式输出数据。在XSLT中,我们通常使用元素来遍历XML中的循环节点并输出内容,for-each元素允许你对要遍历的节点进行排序,参考文章“”。可是,如何在使用for-each元素时对要遍历的节点进行distinct操作以消除重复节点呢?先看下面的XML片段:

<
addresses
>
  
<
address
>
    
<
state
>FL
</
state
>
  
</
address
>
  
<
address
>
    
<
state
>GA
</
state
>
  
</
address
>
  
<
address
>
    
<
state
>MN
</
state
>
  
</
address
>
  
<
address
>
    
<
state
>FL
</
state
>
  
</
address
>
</
addresses
>

  如何编写XSLT代码让其输出为下面的内容?

<
states
>
  
<
state
>FL
</
state
>
  
<
state
>GA
</
state
>
  
<
state
>MN
</
state
>
</
states
>

  注意,上面的XML片段中,节点<address/>为重复节点,并且子节点<state/>存在重复的值,在输出的内容中将去掉这些具有重复节点。我们可以定义一个元素: 

<
xsl:key 
name
=”distinctState” 
match
=”addresses/address” 
use
=”./state”></xsl:key>

   Key元素必须定义在元素xsl:template的外面,与元素xsl:template平级。在上面的key元素中,我们将key应用到addresses/address节点上,并规定该key的表达式为节点state的值。函数用于返回唯一标识指定节点的字符串值。然后,我们在for-each元素中这样使用:

<
xsl:key 
name
="distinctState"
 match
="addresses/address"
 use
="./state"
></
xsl:key
>
<
xsl:template 
match
="/"
>
  
<
states
>
      
<
xsl:for-each 
select
="addresses/address[generate-id() = generate-id(key('distinctState', ./state))]"
>
        
<
state
>
          
<
xsl:value-of 
select
="./state"
></
xsl:value-of
>
        
</
state
>
      
</
xsl:for-each
>
  
</
states
>
</
xsl:template>

   key元素的表达式中也可以使用函数来进行更加精确的匹配,如:

<
xsl:key 
name
="distinctState"
 match
="/Customers/Customer"
 use
="substring(Address, string-length(Address)-1)"
></
xsl:key
>
<
xsl:template 
match
="/"
>
  
<
xsl:for-each 
select
="Customers/Customer[generate-id() = generate-id(key('distinctState', substring(Address, (string-length(Address)-1))))]"
>
    
<
xsl:call-template 
name
="AggregateForState"
>
      
<
xsl:with-param 
name
="state"
 select
="substring(Address, (string-length(Address)-1))"
/>
    
</
xsl:call-template
>
  
</
xsl:for-each
>
</
xsl:template
>

  在看一个复杂点的例子,对XML元素进行分组输出: 

<
items
>
  
<
item
>
    
<
name
>name1
</
name
>
    
<
group
>group1
</
group
>
  
</
item
>
  
<
item
>
    
<
name
>name2
</
name
>
    
<
group
>group1
</
group
>
  
</
item
>
  
<
item
>
    
<
name
>name3
</
name
>
    
<
group
>group2
</
group
>
  
</
item
>
  
<
item
>
    
<
name
>name4
</
name
>
    
<
group
>group2
</
group
>
  
</
item
>
  
<
item
>
    
<
name
>name5
</
name
>
    
<
group
>group2
</
group
>
  
</
item
>
  
<
item
>
    
<
name
>name6
</
name
>
    
<
group
>group1
</
group
>
  
</
item
>
  
<
item
>
    
<
name
>name7
</
name
>
    
<
group
>group3
</
group
>
  
</
item
>
  
<
item
>
    
<
name
>name8
</
name
>
    
<
group
>group3
</
group
>
  
</
item
>
  
<
item
>
    
<
name
>name9
</
name
>
    
<
group
>group4
</
group
>
  
</
item
>
  
<
item
>
    
<
name
>name10
</
name
>
    
<
group
>group1
</
group
>
  
</
item
>
</
items
>

  我们希望编写XSLT将上面的XML解析成下面的样子:

 

  完整的XSLT代码如下:

<?
xml version="1.0" encoding="utf-8"
?>
<
xsl:stylesheet 
version
="1.0"
 xmlns:xsl
="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl
="urn:schemas-microsoft-com:xslt"
 exclude-result-prefixes
="msxsl"
>
  
<
xsl:output 
method
="html"
 indent
="yes"
 omit-xml-declaration
="yes"
/>
  
<
xsl:key 
name
="distinctState"
 match
="items/item"
 use
="./group"
/>
  
<
xsl:template 
match
="/"
>
    
<
xsl:variable 
name
="tabStr"
>
      
<
xsl:for-each 
select
="items/item[generate-id()=generate-id(key('distinctState', ./group))]"
>
        
<
xsl:value-of 
select
="./group"
/>
        
<
xsl:if 
test
="position()!=last()"
>|
</
xsl:if
>
      
</
xsl:for-each
>
    
</
xsl:variable
>
    tabStr: 
<
xsl:value-of 
select
="$tabStr"
/>
    
<
br
/>
    
<
br
/>
    
<
xsl:for-each 
select
="items/item[generate-id()=generate-id(key('distinctState', ./group))]"
>
      
<
xsl:variable 
name
="tabName"
>
        
<
xsl:call-template 
name
="output-tokens"
>
          
<
xsl:with-param 
name
="list"
 select
="$tabStr"
 
/>
          
<
xsl:with-param 
name
="separator"
>|
</
xsl:with-param
>
          
<
xsl:with-param 
name
="pos"
 select
="position()"
/>
        
</
xsl:call-template
>
      
</
xsl:variable
>
      
<
xsl:value-of 
select
="$tabName"
/>
      
<
br
/>
      
<
hr
/>
      
<
xsl:for-each 
select
="//items/item"
>
        
<
xsl:if 
test
="./group = $tabName"
>
          
<
xsl:value-of 
select
="name"
/>
          
<
br
/>
        
</
xsl:if
>
      
</
xsl:for-each
>
      
<
br
/>
    
</
xsl:for-each
>
  
</
xsl:template
>
  
<
xsl:template 
name
="output-tokens"
>
    
<
xsl:param 
name
="list"
 
/>
    
<
xsl:param 
name
="separator"
 
/>
    
<
xsl:param 
name
="pos"
 
/>
    
<
xsl:variable 
name
="newlist"
 select
="concat(normalize-space($list), $separator)"
 
/>
    
<
xsl:variable 
name
="first"
 select
="substring-before($newlist, $separator)"
 
/>
    
<
xsl:variable 
name
="remaining"
 select
="substring-after($newlist, $separator)"
 
/>
    
<
xsl:choose
>
      
<
xsl:when 
test
="$pos = 1"
>
        
<
xsl:value-of 
select
="$first"
/>
      
</
xsl:when
>
      
<
xsl:otherwise
>
        
<
xsl:call-template 
name
="output-tokens"
>
          
<
xsl:with-param 
name
="list"
 select
="$remaining"
 
/>
          
<
xsl:with-param 
name
="separator"
 select
="$separator"
 
/>
          
<
xsl:with-param 
name
="pos"
 select
="$pos - 1"
/>
        
</
xsl:call-template
>
      
</
xsl:otherwise
>
    
</
xsl:choose
>
  
</
xsl:template
>
</
xsl:stylesheet
>

  在上面的代码中,我们首先定义了元素key,并应用到节点items/item上,表达式为“./group”。变量tabStr用来存放以字符“|”分隔的group节点的值,并使用了distinct操作。接下来我们在页面上打印了变量tabStr的值。紧接着的for-each元素则将整个XML文档按照group分组进行输出。注意自定义的template “output-tokens”,在其中使用了一点技巧用来按不同的分组找出对应的分组名称,类似于C#中将字符串使用Split函数存放到数组中。有关output-tokens模板的技巧可以参考我的另一篇文章“”。

  在XSLT的使用中有许多的技巧,灵活掌握这些技巧可以大大缩短我们的开发时间。

转载地址:http://qvttl.baihongyu.com/

你可能感兴趣的文章
Unity strip engine code 遇到執行不能之問題與解決
查看>>
关于Excle中的VLookUp的函数的使用
查看>>
Azure China (10) 使用Azure China SAS Token
查看>>
Spring-AOP实践 - 统计访问时间
查看>>
电子技术·笔记6(2013-05\06)
查看>>
Makefile简易模板
查看>>
Windows Azure Storage (23) 计算Azure VHD实际使用容量
查看>>
压力测试工具Siege介绍
查看>>
ASP.NET如何调用MySQL的存储过程
查看>>
Visual Studio 进行Excel相关开发,Microsoft.Office.Interop.Excel.dll库
查看>>
swfdump——从内存中提取swf的工具
查看>>
【Javascript Demo】JS获取当前对象大小以及屏幕分辨率等
查看>>
Android去掉顶部的阴影
查看>>
卡尔曼滤波的原理说明
查看>>
C#对二进制文件的特定位置进行读写小结
查看>>
唯一不变的就是一直在变”--“数据”的华丽“变身术”
查看>>
编译器定义的C/C++语言各种基本数据类型的取值范围
查看>>
matlab 程序发布
查看>>
《Effective C#》读书笔记——条目24:用委托实现回调<使用C#表达设计>
查看>>
.Net中DataAdapter批量插入和更新数据总结
查看>>