XSLT 1.0按标签分组

时间:2013-03-27 14:44:11

标签: asp.net xml wcf xslt xslt-1.0

我有以下XML数据:

  <result>
<row>
<CountryId>26</CountryId>
<CountryName>United Kingdom</CountryName>
<NoOfNights>1</NoOfNights>
<AccommodationID>6004</AccommodationID>
<RoomID>1</RoomID>
<RoomName>Double for Sole Use</RoomName>
<RatePlanID>1</RatePlanID>
<RoomRatePlan>Advance</RoomRatePlan>
<NoOfSameTypeRoom>0</NoOfSameTypeRoom>
<RoomSize/>
<Max_Person>1</Max_Person>
<RackRate>189</RackRate>
<CurrencySymbol>&pound;</CurrencySymbol>
<NoOfRoomsAvailable>4</NoOfRoomsAvailable>
<Rate>79.00</Rate>
<RatePerDay>27 Mar 2013_79.00</RatePerDay>
</row>
<row>
<CountryId>26</CountryId>
<CountryName>United Kingdom</CountryName>
<NoOfNights>1</NoOfNights>
<AccommodationID>6004</AccommodationID>
<RoomID>1</RoomID>
<RoomName>Double for Sole Use</RoomName>
<RatePlanID>2</RatePlanID>
<RoomRatePlan>Standard</RoomRatePlan>
<NoOfSameTypeRoom>0</NoOfSameTypeRoom>
<RoomSize/>
<Max_Person>1</Max_Person>
<RackRate>189</RackRate>
<CurrencySymbol>&pound;</CurrencySymbol>
<NoOfRoomsAvailable>5</NoOfRoomsAvailable>
<Rate>89.00</Rate>
<RatePerDay>27 Mar 2013_89.00</RatePerDay>
</row>
<row>
<CountryId>26</CountryId>
<CountryName>United Kingdom</CountryName>
<NoOfNights>1</NoOfNights>
<AccommodationID>6004</AccommodationID>
<RoomID>2</RoomID>
<RoomName>Double Room</RoomName>
<RatePlanID>1</RatePlanID>
<RoomRatePlan>Advance</RoomRatePlan>
<NoOfSameTypeRoom>0</NoOfSameTypeRoom>
<RoomSize/>
<Max_Person>2</Max_Person>
<RackRate>199</RackRate>
<CurrencySymbol>&pound;</CurrencySymbol>
<NoOfRoomsAvailable>5</NoOfRoomsAvailable>
<Rate>89.00</Rate>
<RatePerDay>27 Mar 2013_89.00</RatePerDay>
</row>
 </result>

上面xml的我的XSLT是这样的:

<?xml version="1.0" encoding="utf-8" ?>

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

  <xsl:output omit-xml-declaration="yes" indent="yes" method="xml" />
  <xsl:strip-space elements="*"/>

  <!-- Default template : ignore unrecognized elements and text -->
  <xsl:template match="*|text()" />

  <!-- Match document root : add hotels element and process each children node of result -->
  <xsl:template match="/">
    <hotels>
      <!-- We assume that the XML documents are always going to follow the structure:
             result as the root node and xml_acc elements as its children -->
      <xsl:for-each select="result/row">
        <result>
          <hotel_rooms>
            <xsl:element name="hotel_id">
              <xsl:value-of select="AccommodationID"/>
            </xsl:element>
            <xsl:apply-templates />
          </hotel_rooms>
          <xsl:element name="Rate">
            <xsl:element name="RoomRatePlan">
              <xsl:value-of select="RoomRatePlan"/>
            </xsl:element>
            <xsl:element name="numeric_price">
              <xsl:value-of select="Rate"/>
            </xsl:element>
          </xsl:element>
        </result>
      </xsl:for-each>
    </hotels>
  </xsl:template>

  <!-- Elements to be copied as they are -->

  <xsl:template match="NoOfNights|RoomName|RoomSize|Max_Person|RackRate|RatePerDay|CurrencySymbol|NoOfRoomsAvailable|RoomDescription|RoomFacilities|PolicyComments|Breakfast|Policy|Message">
    <xsl:copy-of select="." />
  </xsl:template>

  <xsl:template match="Photo_Max60">
    <RoomImages>
      <Photo_Max60>
        <xsl:value-of select="." />
      </Photo_Max60>
      <Photo_Max300>
        <xsl:value-of select="../Photo_Max300" />
      </Photo_Max300>
      <Photo_Max500>
        <xsl:value-of select="../Photo_Max500" />
      </Photo_Max500>
    </RoomImages>
  </xsl:template>
</xsl:stylesheet>

在XSLT 1.0中,我想按房间ID和酒店ID进行分组。所以在上面的数据中,我希望得到这样的结果。

<hotels>
     <result>
      <hotel_rooms>
        <hotel_id>6004</hotel_id>
        <NoOfNights>1</NoOfNights>
        <RoomID>1</RoomID>
        <RoomName>Double for Sole Use</RoomName>
        <RoomSize/>
        <Max_Person>1</Max_Person>
        <RackRate>189</RackRate>
        <CurrencySymbol>&pound;</CurrencySymbol>
        <NoOfRoomsAvailable>4</NoOfRoomsAvailable>
        <RatePerDay>27 Mar 2013_79.00</RatePerDay>
     </hotel_rooms>
     <Rate>
     <RoomRatePlan>Advance</RoomRatePlan>
     <numeric_price>79.00</numeric_price>
     <RoomRatePlan>Standard</RoomRatePlan>
      <numeric_price>89.00</numeric_price>
     </Rate>
    </result>
    </result>
    <hotels>

我想要一个xslt文件用于上面需要的xml输出。请帮助..

2 个答案:

答案 0 :(得分:1)

Muenchian方法:

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output indent="yes" />
    <xsl:key name="room-per-hotel" match="result" use="concat(hotel_rooms/hotel_id, '-', hotel_rooms/RoomID)" />
    <xsl:template match="/">
        <hotels>
            <xsl:for-each select="hotels/result[count(. | key('room-per-hotel', concat(hotel_rooms/hotel_id, '-', hotel_rooms/RoomID))[1]) = 1]">
                <xsl:sort select="concat(hotel_rooms/hotel_id, '-', hotel_rooms/RoomID)" />
                <result>
                    <xsl:copy-of select="hotel_rooms"/>
                    <Rate>
                        <xsl:copy-of select="key('room-per-hotel', concat(hotel_rooms/hotel_id, '-', hotel_rooms/RoomID))/Rate/*"/>
                    </Rate>
                </result>
            </xsl:for-each>
        </hotels>
    </xsl:template>
</xsl:stylesheet>

Working example

答案 1 :(得分:0)

那么你的输入和你想要的结果都不是很好,标签没有被正确关闭,并且实体引用&pound;存在于一个未声明的实体,但如果你想与XSLT 1.0组合,那么使用Muenchian grouping查看以下XSLT 1.0示例:

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

<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="group" match="result" use="concat(hotel_rooms/hotel_id, '|', hotel_rooms/RoomID)"/>

<xsl:template match="hotels">
  <xsl:copy>
    <xsl:apply-templates select="result[generate-id() = generate-id(key('group', concat(hotel_rooms/hotel_id, '|', hotel_rooms/RoomID))[1])]"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="result">
  <xsl:copy>
    <xsl:copy-of select="hotel_rooms"/>
    <Rate>
      <xsl:copy-of select="key('group', concat(hotel_rooms/hotel_id, '|', hotel_rooms/RoomID))/Rate/*"/>
    </Rate>
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>

它转换

<hotels>
 <result>
  <hotel_rooms>
    <hotel_id>6004</hotel_id>
    <NoOfNights>1</NoOfNights>
    <RoomID>1</RoomID>
    <RoomName>Double for Sole Use</RoomName>
    <RoomSize/>
    <Max_Person>1</Max_Person>
    <RackRate>189</RackRate>
    <CurrencySymbol>pound</CurrencySymbol>
    <NoOfRoomsAvailable>4</NoOfRoomsAvailable>
    <RatePerDay>27 Mar 2013_79.00</RatePerDay>
 </hotel_rooms>
 <Rate>
 <RoomRatePlan>Advance</RoomRatePlan>
 <numeric_price>79.00</numeric_price>
 </Rate>
</result>
<result>
 <hotel_rooms>
  <hotel_id>6004</hotel_id>
  <NoOfNights>1</NoOfNights>
  <RoomID>1</RoomID>
  <RoomName>Double for Sole Use</RoomName>
  <RoomSize/>
  <Max_Person>1</Max_Person>
  <RackRate>189</RackRate>
  <CurrencySymbol>pound</CurrencySymbol>
  <NoOfRoomsAvailable>5</NoOfRoomsAvailable>
  <RatePerDay>27 Mar 2013_89.00</RatePerDay>
 </hotel_rooms>
  <Rate>
  <RoomRatePlan>Standard</RoomRatePlan>
  <numeric_price>89.00</numeric_price>
  </Rate>
</result>
</hotels>

<hotels>
  <result>
    <hotel_rooms>
      <hotel_id>6004</hotel_id>
      <NoOfNights>1</NoOfNights>
      <RoomID>1</RoomID>
      <RoomName>Double for Sole Use</RoomName>
      <RoomSize />
      <Max_Person>1</Max_Person>
      <RackRate>189</RackRate>
      <CurrencySymbol>pound</CurrencySymbol>
      <NoOfRoomsAvailable>4</NoOfRoomsAvailable>
      <RatePerDay>27 Mar 2013_79.00</RatePerDay>
    </hotel_rooms>
    <Rate>
      <RoomRatePlan>Advance</RoomRatePlan>
      <numeric_price>79.00</numeric_price>
      <RoomRatePlan>Standard</RoomRatePlan>
      <numeric_price>89.00</numeric_price>
    </Rate>
  </result>
</hotels>