如何使用XSL 1列出我的XML中的所有唯一值以及如何在XSL 2中实现相同的值?

时间:2018-01-14 19:22:32

标签: xml xslt xslt-1.0 xslt-2.0

好的,所以我知道XSLT并且练习我从gov uk网站下载了一个数据集。我正在研究一组关于布莱顿和英国霍夫食品工业卫生等级的数据。

我的XML数据文件看起来像这样...... 但是要长得多

<?xml version="1.0" encoding="UTF-8"?>
        <?xml-stylesheet type = "text/xsl" href = "test5.xsl"?> 
<FHRSEstablishment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <Header>
                <ExtractDate>2018-01-13</ExtractDate>
                <ItemCount>3074</ItemCount>
                <ReturnCode>Success</ReturnCode>
            </Header>
                <EstablishmentCollection>
                    <EstablishmentDetail>
                        <FHRSID>736377</FHRSID>
                        <LocalAuthorityBusinessID>2014/00302/COMM</LocalAuthorityBusinessID>
                        <BusinessName>16</BusinessName>
                        <BusinessType>Restaurant/Cafe/Canteen</BusinessType>
                        <BusinessTypeID>1</BusinessTypeID>
                        <AddressLine1>16 Sydney Street</AddressLine1>
                        <AddressLine2>Brighton</AddressLine2>
                        <PostCode>BN1 4EN</PostCode>
                        <RatingValue>5</RatingValue>
                        <RatingKey>fhrs_5_en-GB</RatingKey>
                        <RatingDate>2017-01-12</RatingDate>
                        <LocalAuthorityCode>875</LocalAuthorityCode>
                        <LocalAuthorityName>Brighton and Hove</LocalAuthorityName>
                        <LocalAuthorityWebSite>http://www.brighton-hove.gov.uk/foodsafety</LocalAuthorityWebSite>
                        <LocalAuthorityEmailAddress>ehl.food@brighton-hove.gov.uk</LocalAuthorityEmailAddress>
                            <Scores>
                                <Hygiene>0</Hygiene>
                                <Structural>0</Structural>
                                <ConfidenceInManagement>0</ConfidenceInManagement>
                            </Scores>
                        <SchemeType>FHRS</SchemeType>
                        <NewRatingPending>False</NewRatingPending>
                            <Geocode>
                                <Longitude>-0.13802900000000</Longitude>
                                <Latitude>50.82747700000000</Latitude>
                            </Geocode>
                    </EstablishmentDetail>
                    <EstablishmentDetail>
                        <FHRSID>722916</FHRSID>
                        <LocalAuthorityBusinessID>2014/00536/COMM</LocalAuthorityBusinessID>
                        <BusinessName>18 Grocery</BusinessName>
                        <BusinessType>Retailers - other</BusinessType>
                        <BusinessTypeID>4613</BusinessTypeID>
                        <AddressLine1>Unit 18</AddressLine1>
                        <AddressLine2>Open Market</AddressLine2>
                        <AddressLine3>Marshalls Row</AddressLine3>
                        <AddressLine4>Brighton</AddressLine4>
                        <PostCode>BN1 4JU</PostCode>
                        <RatingValue>4</RatingValue>
                        <RatingKey>fhrs_4_en-GB</RatingKey>
                        <RatingDate>2014-12-01</RatingDate>
                        <LocalAuthorityCode>875</LocalAuthorityCode>
                        <LocalAuthorityName>Brighton and Hove</LocalAuthorityName>
                        <LocalAuthorityWebSite>http://www.brighton-hove.gov.uk/foodsafety</LocalAuthorityWebSite>
                        <LocalAuthorityEmailAddress>ehl.food@brighton-hove.gov.uk</LocalAuthorityEmailAddress>
                            <Scores>
                                <Hygiene>0</Hygiene>
                                <Structural>5</Structural>
                                <ConfidenceInManagement>10</ConfidenceInManagement>
                            </Scores>
                        <SchemeType>FHRS</SchemeType>
                        <NewRatingPending>False</NewRatingPending>
                            <Geocode>
                                <Longitude>-0.13602300000000</Longitude>
                                <Latitude>50.83150100000000</Latitude>
                            </Geocode>
                    </EstablishmentDetail>
                </EstablishmentCollection>
 </FHRSEstablishment>

我感兴趣的是列出 RatingValue 的所有唯一/不同值,以找出所有可能的选项。

我一直在研究和尝试各种不同的方法,但似乎没有什么对我有用。所有其他示例都基于更简单的XML数据,我很难过滤我的文件。

我为 XSL 1.0 提出的代码是:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>  

 <xsl:key name="stars" match="/FHRSEstablishment/EstablishmentCollection/*" use="name()" /> 

 <xsl:template match="/">
    <xsl:for-each select="/FHRSEstablishment/EstablishmentCollection/*
    [count(. | key('stars', name())[1]) = 1]">
        <xsl:sort select="name()" />
        <xsl:value-of select="RatingValue" />
    </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

但我得到的输出只是一个数字 5

我知道从1到5只有5个可用的评级,但我想使用XSL找到它并显示结果。 我也试过这段代码:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>  

 <xsl:key name="stars" match="/FHRSEstablishment/EstablishmentCollection/*" use="name()" /> 

 <xsl:template match="/">
    <xsl:for-each select="/FHRSEstablishment/EstablishmentCollection/*
    [count(. | key('stars', name())[1]) = 1]">
        <xsl:sort select="name()" />
        <xsl:value-of select="name()" />
    </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

但是我得到的输出是: 的 EstablishmentDetail

有人可以帮助并向我解释如何在XSL 1.0中使用“key”并在xsl 2中使用distinct-value函数来实现这一目标吗?

1 个答案:

答案 0 :(得分:1)

对于 XSLT 1.0 ,请考虑将密钥调整为特定值 RatingValue ,然后向下调整树而不是<xsl:for-each>。然后有条件地指定仅使用生成的键来提取那些值,这是不同值的第一个分组:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                              exclude-result-prefixes="xsi">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>  

 <xsl:key name="stars" match="EstablishmentDetail" use="RatingValue" /> 

 <xsl:template match="/FHRSEstablishment">
   <output>
    <xsl:apply-templates select="EstablishmentCollection"/>
   </output>
 </xsl:template>

 <xsl:template match="EstablishmentCollection">
    <xsl:apply-templates select="EstablishmentDetail[generate-id() = 
                                 generate-id(key('stars', RatingValue))]">
          <xsl:sort select="RatingValue" />
    </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="EstablishmentDetail">
   <rating>
      <xsl:value-of select="RatingValue"/>
   </rating>
 </xsl:template>

</xsl:stylesheet>

Demo

对于 XSLT 2.0 ,请考虑缩小 RatingValue 的父级,然后运行<xsl:for-each-group>

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                              exclude-result-prefixes="xsi">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>  

 <xsl:template match="/FHRSEstablishment">
   <output>
    <xsl:apply-templates select="EstablishmentCollection"/>
   </output>
 </xsl:template>

 <xsl:template match="EstablishmentCollection">
    <xsl:for-each-group select="EstablishmentDetail" group-by="RatingValue"> 
      <xsl:sort select="RatingValue"/>
      <rating>
        <xsl:value-of select="RatingValue"/>
      </rating>
    </xsl:for-each-group>
 </xsl:template>

</xsl:stylesheet>

Demo

对于演示,我将发布的XML扩展为包含5,4,4,3的多个 RatingValues (复制元素部分)。注意4不会在输出中重复,值会被排序。

<output>
  <rating>3</rating>
  <rating>4</rating>
  <rating>5</rating>
</output>

对于HTML输出,只需将<output><rating>标记替换为HTML标记:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                              exclude-result-prefixes="xsi">
 <xsl:output omit-xml-declaration="yes" indent="yes" method="html"/>  

 <xsl:key name="stars" match="EstablishmentDetail" use="RatingValue" /> 

 <xsl:template match="/FHRSEstablishment">
   <html>
     <body>
       <xsl:apply-templates select="EstablishmentCollection"/>
     </body>
   </html>
 </xsl:template>

 <xsl:template match="EstablishmentCollection">
    <ul>
       <xsl:apply-templates select="EstablishmentDetail[generate-id() = generate-id(key('stars', RatingValue))]">
          <xsl:sort select="RatingValue" />
       </xsl:apply-templates>
    </ul>
 </xsl:template>

 <xsl:template match="EstablishmentDetail">
   <li>
      <xsl:value-of select="RatingValue"/>
   </li>
 </xsl:template>

</xsl:stylesheet>

输出

<html>
  <body>
    <ul>
      <li>3</li>
      <li>4</li>
      <li>5</li>
    </ul>
  </body>
</html>