จัดกลุ่มตาม XSLT 1.0 กลุ่มของกลุ่ม

ฉันต้องการสร้าง "กลุ่มกลุ่ม" โดยใช้ XSLT

ด้านล่างนี้คือไฟล์ XML และ XSL ของฉัน ฉันใช้ลิงก์ SO นี้เพื่อใช้การจัดกลุ่ม Muenchian ฉันได้พยายามย่อไฟล์ให้สั้นลงและแสดงเฉพาะองค์ประกอบที่จำเป็นซึ่งแสดงถึงปัญหา

ไฟล์ XML

<IO_SearchShoppingFilesResult xmlns="http://schemas.datacontract.org/2004/07/Trevoo.WS.IO.Shopping" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<ShoppingFiles
 xmlns:a="http://schemas.datacontract.org/2004/07/Trevoo.WS.Entities.Shopping"
 xmlns:b="http://schemas.datacontract.org/2004/07/Trevoo.WS.Entities.Air">
    <a:T_ShoppingFile>
        ....
        <b:T_AirBookingItem>
            ...
            <a:LocalPaxType>ADT</a:LocalPaxType>
            ...
        </b:T_AirBookingItem>
        <b:T_AirBookingItem>
            ...
            <a:LocalPaxType>CHD</a:LocalPaxType>
            ...
        </b:T_AirBookingItem>
        <b:T_AirBookingItem>
            ...
            <a:LocalPaxType>INF</a:LocalPaxType>
            ...
        </b:T_AirBookingItem>
        ...
    </a:T_ShoppingFile>

    <a:T_ShoppingFile>
        ....
        <b:T_AirBookingItem>
            ...
            <a:LocalPaxType>ADT</a:LocalPaxType>
            ...
        </b:T_AirBookingItem>
        ...
    </a:T_ShoppingFile>
</ShoppingFiles>
</IO_SearchShoppingFilesResult>

ไฟล์ XSL

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:res="http://schemas.datacontract.org/2004/07/Trevoo.WS.IO.Shopping"
xmlns:a="http://schemas.datacontract.org/2004/07/Trevoo.WS.Entities.Shopping"
xmlns:b="http://schemas.datacontract.org/2004/07/Trevoo.WS.Entities.Air"
xmlns:c="http://schemas.microsoft.com/2003/10/Serialization/Arrays"
xmlns:bb="http://schemas.datacontract.org/2004/07/Trevoo.WS.Entities.Shopping.Views">
<xsl:output method="xml" indent="yes" />


<xsl:key name="travelerGroup"
    match="res:IO_SearchShoppingFilesResult/res:ShoppingFiles/a:T_ShoppingFile[position()=1]/a:AirBookings/b:T_AirBooking/b:BookingItems/b:T_AirBookingItem"
    use="b:PaxReference/a:LocalPaxType" />

<xsl:template match="/">
    <xsl:element name="PNRViewRS">
        <xsl:apply-templates
            select="res:IO_SearchShoppingFilesResult/res:ShoppingFiles" />
    </xsl:element>      
</xsl:template>

<xsl:template match="res:ShoppingFiles">
    <!-- For FareGroup, Traveler, Telephone, EmailAddress -->
    <xsl:apply-templates select="a:T_ShoppingFile" />
    ...
</xsl:template>

<xsl:template match="a:T_ShoppingFile">
    ...
    <xsl:apply-templates
            select="a:AirBookings/b:T_AirBooking/b:BookingItems/b:T_AirBookingItem[generate-id() = generate-id(key('travelerGroup', b:PaxReference/a:LocalPaxType)[1])]" />
    ...
</xsl:template>
...
<xsl:template match="b:T_AirBookingItem">
    ...
                    <!-- Line 1 -->
        <xsl:value-of
            select="count(key('travelerGroup', b:PaxReference/a:LocalPaxType))" />  
    ...

</xsl:template>

As one can see, I have applied key on <b:T_AirBookingItem>. And multiple <b:T_AirBookingItem> are present in multiple <a:T_ShoppingFile>.

ตอนนี้ ฉันต้องการจัดการ <a:T_ShoppingFile> แต่ละรายการแยกกัน จากนั้นใช้การจัดกลุ่มกับ <b:T_AirBookingItem> ทั้งหมดที่อยู่ในนั้น สิ่งที่เกิดขึ้นที่นี่คือโค้ดนี้คือ <b:T_AirBookingItem> ทั้งหมดจาก <a:T_ShoppingFile> ทั้งหมดจะถูกจัดกลุ่มไว้ด้วยกันในแต่ละครั้ง

บรรทัดที่ 1 แสดงผลอย่างใดอย่างหนึ่งของการเปลี่ยนแปลงนี้ ควรแสดงจำนวนทั้งหมด <b:T_AirBookingItem> ของ <a:LocalPaxType> โดยเฉพาะ (เช่น ADT) สำหรับ <a:T_ShoppingFile> รายการเดียว อย่างไรก็ตาม จะพิจารณา <b:T_AirBookingItem> ทั้งหมดใน XML ทั้งหมดแทน

แล้วฉันควรจะได้ ADT จำนวน "1" ที่ไหน ฉันจะได้ "2"

ฉันจะจัดการกับมันได้อย่างไร?


person whitehat    schedule 18.04.2012    source แหล่งที่มา


คำตอบ (1)


ดูเหมือนว่าคุณต้องการใช้คีย์ผสมซึ่งประกอบด้วยองค์ประกอบมากกว่าหนึ่งองค์ประกอบ ในกรณีนี้ คุณกำลังจัดหมวดหมู่ตาม a:T_ShoppingFile และ a:LocalPaxType ดังนั้นคุณอาจต้องการอะไรแบบนี้

<xsl:key 
   name="item" 
   match="b:T_AirBookingItem" 
   use="concat(generate-id(..) , '|', a:LocalPaxType)" />

จากนั้น เพื่อให้แต่ละ a:T_ShoppingFile ได้รับบันทึก a:LocalPaxType ที่ไม่ซ้ำกัน คุณเพียงแค่ทำเช่นนี้

<xsl:apply-templates 
  select="b:T_AirBookingItem[generate-id() 
    = generate-id(key('item', concat(generate-id(..) , '|', a:LocalPaxType))[1])]" />

นี่คือ XSLT ฉบับเต็ม

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:res="http://schemas.datacontract.org/2004/07/Trevoo.WS.IO.Shopping" xmlns:a="http://schemas.datacontract.org/2004/07/Trevoo.WS.Entities.Shopping" xmlns:b="http://schemas.datacontract.org/2004/07/Trevoo.WS.Entities.Air" xmlns:c="http://schemas.microsoft.com/2003/10/Serialization/Arrays" xmlns:bb="http://schemas.datacontract.org/2004/07/Trevoo.WS.Entities.Shopping.Views" exclude-result-prefixes="res a b c bb">
   <xsl:output method="xml" indent="yes"/>

   <xsl:key name="item" match="b:T_AirBookingItem" use="concat(generate-id(..) , '|', a:LocalPaxType)"/>

   <xsl:template match="/">
      <xsl:apply-templates select="//a:T_ShoppingFile"/>
   </xsl:template>

   <xsl:template match="a:T_ShoppingFile">
      <file number="{position()}">
         <xsl:apply-templates select="b:T_AirBookingItem[generate-id() = generate-id(key('item', concat(generate-id(..) , '|', a:LocalPaxType))[1])]"/>
      </file>
   </xsl:template>

   <xsl:template match="b:T_AirBookingItem">
      <result>
         <xsl:value-of select="concat(a:LocalPaxType, ' * ', count(key('item', concat(generate-id(..) , '|', a:LocalPaxType))), '&#13;')"/>
      </result>
   </xsl:template>
</xsl:stylesheet>

เมื่อนำไปใช้กับ XML ของคุณ ผลลัพธ์ต่อไปนี้จะเป็นผลลัพธ์

<file number="1">
   <result>ADT * 1</result>
   <result>CHD * 1</result>
   <result>INF * 1</result>
</file>
<file number="2">
   <result>ADT * 1</result>
</file>

แน่นอนว่าสิ่งนี้จะแสดงผลลัพธ์สำหรับ a:T_ShoppingFile และ a:LocalPaxType ทั้งหมด หากคุณต้องการจำกัดเฉพาะ a:LocalPaxType คุณสามารถดำเนินการเช่นนี้ (แม้ว่าคุณอาจต้องการกำหนดพารามิเตอร์ของค่า แทนที่จะใช้ฮาร์ดโค้ด ADT

   <xsl:template match="a:T_ShoppingFile">
      <file number="{position()}">
         <xsl:value-of select="count(key('item', concat(generate-id() , '|', 'ADT')))" />
      </file>
   </xsl:template>
person Tim C    schedule 18.04.2012
comment
สิ่งนี้มีประโยชน์จริงๆ วิธีแก้ปัญหาของฉันอย่างแน่นอน ขอบคุณ :) - person whitehat; 18.04.2012
comment
ไอเดียการใช้ 'คีย์ผสม' เจ๋งมาก!! - person whitehat; 18.04.2012
comment
ตรวจสอบให้แน่ใจว่าตัวคั่นที่รวมสองส่วนเข้าด้วยกัน (แถบ | ในกรณีนี้) จะไม่เกิดขึ้นในส่วนใดส่วนหนึ่งของคีย์ - person Tim C; 18.04.2012