Как конвертировать мой sql-запрос в xslt? - PullRequest
0 голосов
/ 14 февраля 2012

У меня есть XML-файл

<ServiceHotel>
    <AvailableRoom>
        <HotelOccupancy>
        <RoomCount>1</RoomCount>
        <Occupancy>
            <AdultCount>1</AdultCount>
            <ChildCount>1</ChildCount>
        </Occupancy>
        </HotelOccupancy>
        <HotelRoom>
            <Board>Room Only</Board>
            <RoomType>Double/twin Superior</RoomType>
            <Price>
                <Amount>21.168</Amount>
            </Price>
        </HotelRoom>
  </AvailableRoom>
  <AvailableRoom>
        <HotelOccupancy>
        <RoomCount>1</RoomCount>
        <Occupancy>
            <AdultCount>3</AdultCount>
            <ChildCount>0</ChildCount>
        </Occupancy>
        </HotelOccupancy>
        <HotelRoom>
            <Board>Room Only</Board>
            <RoomType>Twin Superior</RoomType>
            <Price>
                <Amount>34.195</Amount>
            </Price>
        </HotelRoom>
  </AvailableRoom>
  <AvailableRoom>
        <HotelOccupancy>
        <RoomCount>1</RoomCount>
        <Occupancy>
            <AdultCount>1</AdultCount>
            <ChildCount>1</ChildCount>
        </Occupancy>
        </HotelOccupancy>
        <HotelRoom>
            <Board>Room Only</Board>
            <RoomType>Double/twin Superior</RoomType>
            <Price>
                <Amount>25.618</Amount>
            </Price>
        </HotelRoom>
  </AvailableRoom>
  <AvailableRoom>
        <HotelOccupancy>
        <RoomCount>1</RoomCount>
        <Occupancy>
            <AdultCount>3</AdultCount>
            <ChildCount>0</ChildCount>
        </Occupancy>
        </HotelOccupancy>
        <HotelRoom>
            <Board>Room Only</Board>
            <RoomType>Double/twin Superior</RoomType>
            <Price>
                <Amount>38.645</Amount>
            </Price>
        </HotelRoom>
  </AvailableRoom>
  <AvailableRoom>
        <HotelOccupancy>
        <RoomCount>1</RoomCount>
        <Occupancy>
            <AdultCount>1</AdultCount>
            <ChildCount>0</ChildCount>
        </Occupancy>
        </HotelOccupancy>
        <HotelRoom>
            <Board>Room Only</Board>
            <RoomType>Single Superior</RoomType>
            <Price>
                <Amount>25.618</Amount>
            </Price>
        </HotelRoom>
  </AvailableRoom>
  <AvailableRoom>
        <HotelOccupancy>
        <RoomCount>1</RoomCount>
        <Occupancy>
            <AdultCount>1</AdultCount>
            <ChildCount>0</ChildCount>
        </Occupancy>
        </HotelOccupancy>
        <HotelRoom>
            <Board>Room Only</Board>
            <RoomType>Double Superior</RoomType>
            <Price>
                <Amount>19.840</Amount>
            </Price>
        </HotelRoom>
  </AvailableRoom>
  <AvailableRoom>
        <HotelOccupancy>
        <RoomCount>1</RoomCount>
        <Occupancy>
            <AdultCount>3</AdultCount>
            <ChildCount>0</ChildCount>
        </Occupancy>
        </HotelOccupancy>
        <HotelRoom>
            <Board>Bed and Breakfast</Board>
            <RoomType>Twin Superior</RoomType>
            <Price>
                <Amount>34.195</Amount>
            </Price>
        </HotelRoom>
  </AvailableRoom>
  <AvailableRoom>
        <HotelOccupancy>
        <RoomCount>1</RoomCount>
        <Occupancy>
            <AdultCount>3</AdultCount>
            <ChildCount>0</ChildCount>
        </Occupancy>
        </HotelOccupancy>
        <HotelRoom>
            <Board>Bed and Breakfast</Board>
            <RoomType>Double/twin Superior</RoomType>
            <Price>
                <Amount>38.645</Amount>
            </Price>
        </HotelRoom>
  </AvailableRoom>
  <AvailableRoom>
        <HotelOccupancy>
        <RoomCount>1</RoomCount>
        <Occupancy>
            <AdultCount>1</AdultCount>
            <ChildCount>0</ChildCount>
        </Occupancy>
        </HotelOccupancy>
        <HotelRoom>
            <Board>Bed and Breakfast</Board>
            <RoomType>Single Superior</RoomType>
            <Price>
                <Amount>25.618</Amount>
            </Price>
        </HotelRoom>
  </AvailableRoom>
  <AvailableRoom>
        <HotelOccupancy>
        <RoomCount>1</RoomCount>
        <Occupancy>
            <AdultCount>1</AdultCount>
            <ChildCount>0</ChildCount>
        </Occupancy>
        </HotelOccupancy>
        <HotelRoom>
            <Board>Bed and Breakfast</Board>
            <RoomType>Double Superior</RoomType>
            <Price>
                <Amount>19.840</Amount>
            </Price>
        </HotelRoom>
  </AvailableRoom>
  <AvailableRoom>
        <HotelOccupancy>
        <RoomCount>1</RoomCount>
        <Occupancy>
            <AdultCount>3</AdultCount>
            <ChildCount>0</ChildCount>
        </Occupancy>
        </HotelOccupancy>
        <HotelRoom>
            <Board>Full Board</Board>
            <RoomType>Twin Superior</RoomType>
            <Price>
                <Amount>35.195</Amount>
            </Price>
        </HotelRoom>
  </AvailableRoom>
  <AvailableRoom>
        <HotelOccupancy>
        <RoomCount>1</RoomCount>
        <Occupancy>
            <AdultCount>3</AdultCount>
            <ChildCount>0</ChildCount>
        </Occupancy>
        </HotelOccupancy>
        <HotelRoom>
            <Board>Full Board</Board>
            <RoomType>Double/twin Superior</RoomType>
            <Price>
                <Amount>32.645</Amount>
            </Price>
        </HotelRoom>
  </AvailableRoom>
  <AvailableRoom>
        <HotelOccupancy>
        <RoomCount>1</RoomCount>
        <Occupancy>
            <AdultCount>3</AdultCount>
            <ChildCount>0</ChildCount>
        </Occupancy>
        </HotelOccupancy>
        <HotelRoom>
            <Board>Half Board</Board>
            <RoomType>Twin Superior</RoomType>
            <Price>
                <Amount>35.195</Amount>
            </Price>
        </HotelRoom>
  </AvailableRoom>
  <AvailableRoom>
        <HotelOccupancy>
        <RoomCount>1</RoomCount>
        <Occupancy>
            <AdultCount>3</AdultCount>
            <ChildCount>0</ChildCount>
        </Occupancy>
        </HotelOccupancy>
        <HotelRoom>
            <Board>Half Board</Board>
            <RoomType>Double/twin Superior</RoomType>
            <Price>
                <Amount>32.645</Amount>
            </Price>
        </HotelRoom>
  </AvailableRoom>
  <AvailableRoom>
        <HotelOccupancy>
        <RoomCount>1</RoomCount>
        <Occupancy>
            <AdultCount>1</AdultCount>
            <ChildCount>0</ChildCount>
        </Occupancy>
        </HotelOccupancy>
        <HotelRoom>
            <Board>Half Board</Board>
            <RoomType>Single Superior</RoomType>
            <Price>
                <Amount>28.618</Amount>
            </Price>
        </HotelRoom>
  </AvailableRoom>
  <AvailableRoom>
        <HotelOccupancy>
        <RoomCount>1</RoomCount>
        <Occupancy>
            <AdultCount>1</AdultCount>
            <ChildCount>0</ChildCount>
        </Occupancy>
        </HotelOccupancy>
        <HotelRoom>
            <Board>Half Board</Board>
            <RoomType>Double Superior</RoomType>
            <Price>
                <Amount>20.840</Amount>
            </Price>
        </HotelRoom>
  </AvailableRoom>
  <AvailableRoom>
        <HotelOccupancy>
        <RoomCount>1</RoomCount>
        <Occupancy>
            <AdultCount>1</AdultCount>
            <ChildCount>1</ChildCount>
        </Occupancy>
        </HotelOccupancy>
        <HotelRoom>
            <Board>Half Board</Board>
            <RoomType>Double/twin Superior</RoomType>
            <Price>
                <Amount>30.168</Amount>
            </Price>
        </HotelRoom>
  </AvailableRoom>
</ServiceHotel>

Я конвертирую приведенный выше xml в sql запрос, как показано ниже

SET NOCOUNT ON DECLARE @Product TABLE (
Total_Adults VarChar(50) ,
Board_Type VarChar(100) , 
Room_Type VarChar(150) ,
Room_Count VarChar(10) ,
Adults VarChar(10) ,
Child VarChar(10) ,
Price Float(53) 
); 
INSERT INTO @Product Values ('111','Room Only','Double/twin Superior','1','1','1','21.168'); 
INSERT INTO @Product Values ('130','Room Only','Twin Superior','1','3','0','34.195'); 
INSERT INTO @Product Values ('111','Room Only','Double/twin Superior','1','1','1','25.618'); 
INSERT INTO @Product Values ('130','Room Only','Double/twin Superior','1','3','0','38.645'); 
INSERT INTO @Product Values ('110','Room Only','Single Superior','1','1','0','25.618');
INSERT INTO @Product Values ('110','Room Only','Double Superior','1','1','0','19.840'); 

INSERT INTO @Product Values ('130','Bed and Breakfast','Twin Superior','1','3','0','34.195'); 
INSERT INTO @Product Values ('130','Bed and Breakfast','Double/twin Superior','1','3','0','38.645'); 
INSERT INTO @Product Values ('110','Bed and Breakfast','Single Superior','1','1','0','25.618');
INSERT INTO @Product Values ('110','Bed and Breakfast','Double Superior','1','1','0','19.840'); 

INSERT INTO @Product Values ('130','Full Board','Twin Superior','1','3','0','35.195'); 
INSERT INTO @Product Values ('130','Full Board','Double/twin Superior','1','3','0','32.645'); 

INSERT INTO @Product Values ('130','Half Board','Twin Superior','1','3','0','35.195'); 
INSERT INTO @Product Values ('130','Half Board','Double/twin Superior','1','3','0','32.645'); 
INSERT INTO @Product Values ('110','Half Board','Single Superior','1','1','0','28.618');
INSERT INTO @Product Values ('110','Half Board','Double Superior','1','1','0','20.840'); 
INSERT INTO @Product Values ('111','Half Board','Double/twin Superior','1','1','1','30.168'); 

WITH CTE1 AS (
SELECT ROW_NUMBER() OVER(PARTITION BY Total_Adults, Board_Type, Room_Type ORDER BY Price ASC
) AS RN, * FROM @Product)
,CTE2 AS ( SELECT * FROM CTE1 WHERE RN = 1)
,CTE3 As (Select *,Count(*) over()as Frequency 
, row_number()over(partition by Total_Adults, Board_Type order by Price ASC) as RNN from CTE2)
,CTE4 As (
select *, Count(Board_Type) over (partition by Board_Type) as RC from CTE3 where RNN=1)
Select SUM(Price) over (partition by Board_Type) as Grand_Total,* from CTE4 where RC='3' 
ORDER BY Grand_Total ASC, MIN(Price) OVER(PARTITION BY Board_Type),Board_Type,Price; 

вывод моего sql-запроса

Grand_Total, Total_Adults,  Board_Type,  Room_Type,  Room_Count,  Adults, Child, Price
75.203  110 Room Only   Double Superior           1    1    0    19.84
75.203  111 Room Only   Double/twin Superior      1    1    1    21.168
75.203  130 Room Only   Twin Superior             1    3    0    34.195
83.653  110 Half Board  Double Superior           1    1    0    20.84
83.653  111 Half Board  Double/twin Superior      1    1    1    30.168
83.653  130 Half Board  Double/twin Superior      1    3    0    32.645 

Мне нужно создать файл XSL 1.0 для получения этого вывода. (эквивалент SQL-запроса)

я пытаюсь выполнить запрос ниже, но не работает нормально

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="html" indent="yes"/>
  <xsl:key name="by-board" match="AvailableRoom" use="HotelRoom/Board"/>

    <xsl:key name="by-b" match="AvailableRoom" use="concat(HotelRoom/Board,'|',HotelOccupancy/Occupancy/AdultCount , '|',HotelOccupancy/Occupancy/ChildCount)"/>

  <xsl:key name="TotalAdults" match="HotelOccupancy" use="concat(Occupancy/AdultCount, '|', Occupancy/ChildCount)" />
  <xsl:variable name="TotalRoomCount" select="count(/ServiceHotel/AvailableRoom/HotelOccupancy [generate-id(.) = generate-id(key('TotalAdults', concat(Occupancy/AdultCount, '|', Occupancy/ChildCount))[1])])" />


  <xsl:template match="/">
  <table cellpadding="0" cellspacing="0"  border="1">

    <tr>
        <td height="28" width="290"><font face="Arial" size="2">Room Type</font></td>
        <td height="28" width="302"><font face="Arial" size="2">Board Type</font></td>
        <td height="28" width="51" align="center"><font face="Arial" size="2">R.Count</font></td>
        <td height="28" width="52" align="center"><font face="Arial" size="2">A.Count</font></td>
        <td height="28" width="52" align="center"><font face="Arial" size="2">C.Count</font></td>
        <td height="28" width="89" align="center"><font face="Arial" size="2">Price</font></td>
    </tr>
    <xsl:apply-templates select="ServiceHotel" />
    </table>
  </xsl:template>

  <xsl:template match="ServiceHotel">
      <xsl:for-each select="AvailableRoom[generate-id() = generate-id(key('by-board', HotelRoom/Board)[1]) 
                             and count(key('by-board', HotelRoom/Board)) >= 
                                $TotalRoomCount 

                                ]">
        <xsl:sort select="sum(key('by-board', HotelRoom/Board)[position() &lt; 4]/HotelRoom/Price/Amount)"/>


       <xsl:apply-templates select="." mode="group"/>

      </xsl:for-each>
  </xsl:template>

  <xsl:template match="AvailableRoom" mode="group">

    <xsl:apply-templates select="key('by-board', HotelRoom/Board)[generate-id() = generate-id(key('by-b', 
    concat(HotelRoom/Board,'|',HotelOccupancy/Occupancy/AdultCount , '|',HotelOccupancy/Occupancy/ChildCount)
    )[1]) 
     ]">

                              <xsl:sort select="HotelRoom/Price/Amount" data-type="number"/>
      </xsl:apply-templates>



    <tr>
        <td height="28" width="290" bgcolor="#FFFFCC"><font face="Arial" size="2"></font></td>
        <td height="28" width="302" bgcolor="#FFFFCC"><font face="Arial" size="2"></font></td>
        <td height="28" width="51" align="center" bgcolor="#FFFFCC"><font face="Arial" size="2"></font></td>
        <td height="28" width="52" align="center" bgcolor="#FFFFCC"><font face="Arial" size="2"></font></td>
        <td height="28" width="52" align="center" bgcolor="#FFFFCC"><font face="Arial" size="2"></font></td>
        <td height="28" width="89" align="center" bgcolor="#FFFFCC"><font face="Arial" size="2"><xsl:value-of select="format-number(sum(key('by-board', HotelRoom/Board)[position() &lt; 4] /HotelRoom/Price/Amount), '#.000')"/></font></td>
    </tr>


  </xsl:template>

  <xsl:template match="AvailableRoom">


        <tr>
        <td height="28" width="290"><font face="Arial" size="2"><xsl:value-of select="HotelRoom/RoomType"/></font></td>
        <td height="28" width="302"><font face="Arial" size="2"><xsl:value-of select="HotelRoom/Board"/></font></td>
                <td height="28" width="51" align="center"><font face="Arial" size="2"><xsl:value-of select="HotelOccupancy/RoomCount"/></font></td>
                <td height="28" width="52" align="center"><font face="Arial" size="2"><xsl:value-of select="HotelOccupancy/Occupancy/AdultCount"/></font></td>
                <td height="28" width="52" align="center"><font face="Arial" size="2"><xsl:value-of select="HotelOccupancy/Occupancy/ChildCount"/></font></td>
        <td height="28" width="89" align="center"><font face="Arial" size="2"><xsl:value-of select="format-number(HotelRoom/Price/Amount, '#.000')"/></font></td>
        </tr>        
  </xsl:template>
</xsl:stylesheet>

1 Ответ

0 голосов
/ 15 февраля 2012

Я полагаю, что вы хотите сказать, что вы хотите, чтобы ваш XSLT выводил ту же таблицу, которая в данный момент выводится вашим примером SQL.

Я мог бы добиться этого, используя набор узлов функция расширения.Когда вы «группируете» тип доски, а не просто выводите группы комнат, результаты сохраняются в переменной.

  <xsl:variable name="rooms">
     <xsl:apply-templates 
        select="//AvailableRoom
           [HotelRoom/Board = current()/HotelRoom/Board]
           [generate-id() = generate-id(key('by-b', concat(HotelRoom/Board,'|',HotelOccupancy/Occupancy/AdultCount , '|',HotelOccupancy/Occupancy/ChildCount))[1])]" mode="room" />
  </xsl:variable>

Это позволяет исключить доску элементы, в которых содержится менее трех элементов, например

<xsl:if test="count(ns:node-set($rooms)/AvailableRoom) >= 3">

Вот полный XSLT

<xsl:stylesheet version="1.0"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
   xmlns:ns="urn:schemas-microsoft-com:xslt"
   exclude-result-prefixes="ns">

   <xsl:output method="html" indent="yes"/>

   <xsl:key name="by-board" match="AvailableRoom" use="HotelRoom/Board" />
   <xsl:key name="by-b" match="AvailableRoom" use="concat(HotelRoom/Board,'|',HotelOccupancy/Occupancy/AdultCount , '|',HotelOccupancy/Occupancy/ChildCount)"/>     

   <xsl:template match="/ServiceHotel">
      <table border="1">
    <tr>
          <td>Grand Total</td>
          <td>Total Adults?</td>
          <td>Board Type</td>
          <td>Room Type</td>
          <td>Room Count</td>
          <td>Adults</td>
          <td>Child</td>
          <td>Price</td>
       </tr>       
         <xsl:apply-templates select="AvailableRoom[generate-id() = generate-id(key('by-board',HotelRoom/Board)[1])]" mode="board" />
      </table>
   </xsl:template>

   <xsl:template match="AvailableRoom" mode="board">
      <xsl:variable name="rooms">
         <xsl:apply-templates 
            select="//AvailableRoom
               [HotelRoom/Board = current()/HotelRoom/Board]
               [generate-id() = generate-id(key('by-b', concat(HotelRoom/Board,'|',HotelOccupancy/Occupancy/AdultCount , '|',HotelOccupancy/Occupancy/ChildCount))[1])]" mode="room" />
      </xsl:variable>
      <xsl:if test="count(ns:node-set($rooms)/AvailableRoom) >= 3">
         <xsl:apply-templates select="ns:node-set($rooms)/AvailableRoom">
            <xsl:with-param name="total" select="sum(ns:node-set($rooms)/AvailableRoom/HotelRoom/Price/Amount)" />
            <xsl:sort select="HotelRoom/Price/Amount" />
         </xsl:apply-templates>
      </xsl:if>
   </xsl:template>

   <xsl:template match="AvailableRoom" mode="room">
      <xsl:for-each select="key('by-b', concat(HotelRoom/Board,'|',HotelOccupancy/Occupancy/AdultCount , '|',HotelOccupancy/Occupancy/ChildCount))">
         <xsl:sort select="HotelRoom/Price/Amount" />
         <xsl:if test="position() = 1">
            <xsl:copy-of select="." />
         </xsl:if>
      </xsl:for-each>
   </xsl:template>

   <xsl:template match="AvailableRoom">
      <xsl:param name="total" />
      <tr>
         <td>
            <xsl:value-of select="format-number($total, '0.00')" />
         </td>
         <td>
            <xsl:value-of select="HotelOccupancy/RoomCount"/>
            <xsl:value-of select="HotelOccupancy/Occupancy/AdultCount"/>
            <xsl:value-of select="HotelOccupancy/Occupancy/ChildCount"/>         
         </td>
         <td>
            <xsl:value-of select="HotelRoom/Board"/>
         </td>
         <td>
            <xsl:value-of select="HotelRoom/RoomType"/>
         </td>
         <td>
            <xsl:value-of select="HotelOccupancy/RoomCount"/>
         </td>
         <td>
            <xsl:value-of select="HotelOccupancy/Occupancy/AdultCount"/>
         </td>
         <td>
            <xsl:value-of select="HotelOccupancy/Occupancy/ChildCount"/>
         </td>
         <td>
            <xsl:value-of select="HotelRoom/Price/Amount"/>
         </td>
      </tr>
   </xsl:template>   
</xsl:stylesheet>

При применении к вашему образцу XML выдается следующее

<table border="1">
   <tr>
      <td>Grand Total</td>
      <td>Total Adults?</td>
      <td>Board Type</td>
      <td>Room Type</td>
      <td>Room Count</td>
      <td>Adults</td>
      <td>Child</td>
      <td>Price</td>
   </tr>
   <tr>
      <td>75.20</td>
      <td>110</td>
      <td>Room Only</td>
      <td>Double Superior</td>
      <td>1</td>
      <td>1</td>
      <td>0</td>
      <td>19.840</td>
   </tr>
   <tr>
      <td>75.20</td>
      <td>111</td>
      <td>Room Only</td>
      <td>Double/twin Superior</td>
      <td>1</td>
      <td>1</td>
      <td>1</td>
      <td>21.168</td>
   </tr>
   <tr>
      <td>75.20</td>
      <td>130</td>
      <td>Room Only</td>
      <td>Twin Superior</td>
      <td>1</td>
      <td>3</td>
      <td>0</td>
      <td>34.195</td>
   </tr>
   <tr>
      <td>83.65</td>
      <td>110</td>
      <td>Half Board</td>
      <td>Double Superior</td>
      <td>1</td>
      <td>1</td>
      <td>0</td>
      <td>20.840</td>
   </tr>
   <tr>
      <td>83.65</td>
      <td>111</td>
      <td>Half Board</td>
      <td>Double/twin Superior</td>
      <td>1</td>
      <td>1</td>
      <td>1</td>
      <td>30.168</td>
   </tr>
   <tr>
      <td>83.65</td>
      <td>130</td>
      <td>Half Board</td>
      <td>Double/twin Superior</td>
      <td>1</td>
      <td>3</td>
      <td>0</td>
      <td>32.645</td>
   </tr>
</table>

Обратите внимание, функция расширения во многом зависит от того, какой процессор вы используете.В этом случае я использую Mircosoft, и поэтому пространство имен для функции расширения - urn: schemas-microsoft-com: xslt.Если вы не используете это, вам нужно будет найти, какой из них поддерживается;наиболее вероятно http://exslt.org/common

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...