如何从XSL转换中获取唯一值?

时间:2013-03-22 19:17:02

标签: xml xpath xslt

我有以下XML文件:

<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="cars.xsd">
<manufacture id="1">
    <make>Audi</make>
    <classification>
        <list mid="1">
            <type>Sports</type>
        </list>     
        <list  mid="2">
            <type>Compact</type>
        </list>     
        <list  mid="3">
            <type>Compact</type>
        </list> 
    </classification>
</manufacture>
<manufacture id="2">
    <make>bmw</make>
    <classification>
        <list mid="1">
            <type>Sports</type>
        </list>     
        <list  mid="2">
            <type>Luxury</type>
        </list> 
        <list  mid="3">
            <type>Luxury</type>
        </list>                 
    </classification>
</manufacture>
</document>

这是我当前的XSL代码:

<?xml version="1.0" encoding="ISO-8859-1"?>

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 <xsl:output doctype-public="-//WAPFORUM//DTD XHTML Mobile 1.0//EN" 
            doctype-system="http://www.wapforum.org/DTD/xhtml-mobile10.dtd"
 method="xml" version="1.0" 
            omit-xml-declaration="yes" 
            indent="yes" encoding="UTF-8" media-type="text/html"/>

<xsl:template match="/">
<xsl:element name="html">
<xsl:element name="head">           
    <xsl:element name="title">Automotives</xsl:element>
</xsl:element>

<xsl:element name="body">                    
<xsl:element name="ul">
<xsl:attribute name="class">pageitem</xsl:attribute>                    
    <xsl:for-each select="document/manufacture/classification/list">        
        <xsl:element name="li">
        <xsl:attribute name="class">menu</xsl:attribute>        
            <xsl:element name="p">
            <xsl:attribute name="class">name</xsl:attribute>
              <xsl:element name="a">                                
                    <xsl:value-of select="type"/>
                    <xsl:element name="br"/>    
                </xsl:element>      
            </xsl:element>
        </xsl:element>                    
    </xsl:for-each>
</xsl:element>      
</xsl:element>  
</xsl:element>
</xsl:template>
</xsl:stylesheet>

如何在不重复类型的情况下获得以下输出?

Sports
Compact 
Luxury

我是XSLT的新手,我尝试过使用generate-id(),如:Select once from duplicate XML info, display rest, and sort on a field

但它对我不起作用,因为我无法理解generate-id()代码。

1 个答案:

答案 0 :(得分:4)

你提到了generate-id,这意味着你可能已经在这里阅读了Muenchian Grouping,这确实是获得不同值所需要的。由于您对类型元素感兴趣,因此您可以从我的定义键开始,以便根据其值轻松查找这些元素。

<xsl:key name="types" match="type" use="." />

现在,要获取不同的元素,您将遍历所有类型元素,但只输出不同的元素。并告诉他们是不同的,你检查它们是否首先出现在他们给定值的密钥中。

这是表达式......

<xsl:apply-templates select="//type[generate-id() = generate-id(key('types', .)[1])]" />

但要将其分解为其主要部分......

key('types', .) - 返回当前值的所有类型元素

key('types', .)[1] - 返回键中的第一个元素

generate-id(key('types', .)[1]) - 返回该元素的唯一标识符

generate-id() = generate-id(key('types', .)[1]) - 检查当前元素的唯一标识符是否等于键中第一个元素的唯一标识符。

因此,如果它们匹配,则它是第一次出现,并且可以输出。

这是完整的XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="text" />
   <xsl:key name="types" match="type" use="." />

   <xsl:template match="/">
      <xsl:apply-templates select="//type[generate-id() = generate-id(key('types', .)[1])]" />
   </xsl:template>

    <xsl:template match="type">
      <xsl:value-of select="concat(., '&#10;')" />
   </xsl:template>
</xsl:stylesheet>

当应用于您的XML时,输出以下内容

Sports
Compact
Luxury