0

我正在与一个营销平台合作,以展示一个人为航班订购的包。作为整个旅程的一部分,一名乘客可以有多个航段。因此,如果我们有像下面这样的记录(每条记录也分配了一个唯一值,因为这在被拉出之前全部插入到数据库中,这里的 xml 是我正在使用的模型)。

编辑 8/9 - 下面的实际 XML 和修订的 XSLT。此外,如果您查看 Bag 部分中的此链接(http://f.spiritairlines.com/ats/msg.aspx?sg1=2e4a4d00cb00be84c598b618d6556e3e)。我希望它看起来像第二行(Pedro Smith)而不是第一行(Sandra Smith)。顺便说一句,这是所有测试数据,因此向您展示没有隐私问题,也没有任何私人信息。

<bookingcontact_to_booking>
    <passenger_to_bookings> 
        <passenger_to_booking>
            <Prop pk_id="4147" entity_id="126" val="SMITH" type_id="20" prop_name="lastname" prop_id="10208"/>
            <Prop pk_id="4147" entity_id="126" val="PEDRO" type_id="20" prop_name="firstname" prop_id="10206"/>
            <passseg_to_passengers>
                <passseg_to_passenger>
                    <Prop pk_id="9432" entity_id="122" val="2013-08-27 17:45:00.000" type_id="30" prop_name="arrivaltime" prop_id="10216"/>
                    <Prop pk_id="9432" entity_id="122" val="188" type_id="20" prop_name="flightnumber" prop_id="10217"/>
                    <Prop pk_id="9432" entity_id="122" val="5" type_id="10" prop_name="checkedbagcount" prop_id="10220"/>
                    <Prop pk_id="9432" entity_id="122" val="1" type_id="10" prop_name="carryonbagcount" prop_id="10221"/>
                    <Prop pk_id="9432" entity_id="122" val="1" type_id="10" prop_name="journeynumber" prop_id="10222"/>
                    <Prop pk_id="9432" entity_id="122" val="0" type_id="10" prop_name="segmentnumber" prop_id="10223"/>
                    <Prop pk_id="9432" entity_id="122" val="2013-08-27 08:12:00.000" type_id="30" prop_name="departuretime" prop_id="10296"/>
                    <Prop pk_id="9432" entity_id="122" val="Las Vegas, NV" type_id="20" prop_name="departureairport" prop_id="10297"/>
                    <Prop pk_id="9432" entity_id="122" val="New York, NY - LaGuardia " type_id="20" prop_name="arrivalairport" prop_id="10298"/>
                    <Prop pk_id="9432" entity_id="122" val="10B,20B" type_id="20" prop_name="seatassignment" prop_id="10299"/>
                </passseg_to_passenger>
                <passseg_to_passenger>
                    <Prop pk_id="9433" entity_id="122" val="10B,20B" type_id="20" prop_name="seatassignment" prop_id="10299"/>
                    <Prop pk_id="9433" entity_id="122" val="Fort Lauderdale, FL" type_id="20" prop_name="arrivalairport" prop_id="10298"/>
                    <Prop pk_id="9433" entity_id="122" val="New York, NY - LaGuardia " type_id="20" prop_name="departureairport" prop_id="10297"/>
                    <Prop pk_id="9433" entity_id="122" val="2013-08-27 19:45:00.000" type_id="30" prop_name="departuretime" prop_id="10296"/>
                    <Prop pk_id="9433" entity_id="122" val="1" type_id="10" prop_name="segmentnumber" prop_id="10223"/>
                    <Prop pk_id="9433" entity_id="122" val="1" type_id="10" prop_name="journeynumber" prop_id="10222"/>
                    <Prop pk_id="9433" entity_id="122" val="1" type_id="10" prop_name="carryonbagcount" prop_id="10221"/>
                    <Prop pk_id="9433" entity_id="122" val="5" type_id="10" prop_name="checkedbagcount" prop_id="10220"/>
                    <Prop pk_id="9433" entity_id="122" val="779" type_id="20" prop_name="flightnumber" prop_id="10217"/>
                    <Prop pk_id="9433" entity_id="122" val="2013-08-27 22:45:00.000" type_id="30" prop_name="arrivaltime" prop_id="10216"/>
                </passseg_to_passenger>
            </passseg_to_passengers>
        </passenger_to_booking>
    </passenger_to_bookings>
</bookingcontact_to_booking>

我只想在每次旅程中显示 CarryOnBagCount 和 CheckedBagCount 一次。我尝试了几种不同的方法,但我认为我离解决方案越来越远。目前,无论旅程和航段如何,输出都是所有行李数量。XSLT 如下。

<?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" encoding="UTF-8" indent="yes" omit-xml-declaration="yes" />

    <xsl:key name="journey" match="passengersegment" use="Prop[@prop_name = 'journeynumber']/@val"/>

    <xsl:template match="/">
        <xsl:for-each select="/Msg/Props/bookingcontact_to_booking/passenger_to_bookings/passenger_to_booking">
            <tr>
                <td colspan="3">
                    <table style="text-align: left; line-height: 18px; font-family: Arial, Helvetica, sans-serif; font-size: 12px; color:#333333;"
                    border="0" cellspacing="0" cellpadding="0" width="542" align="left">
                        <tbody>
                            <tr>
                                <td height="22" width="200">
                                    <xsl:value-of select="Prop[@prop_name = 'firstname']/@val" /><xsl:text> </xsl:text><xsl:value-of select="Prop[@prop_name = 'lastname']/@val" />
                                </td>
                                <xsl:apply-templates select="passengersegment[generate-id() = generate-id(key('journey', journeynumber)[1])]"/>
                            </tr>
                        </tbody>
                    </table>
                </td>
            </tr>
        </xsl:for-each>
    </xsl:template>

    <xsl:template match="passengersegment">
        <td style="text-align: left;" width="100">
            <table style="text-align: left; line-height: 18px; font-family: Arial, Helvetica, sans-serif; font-size: 12px; color:#333333;" width="100">
                <tr>
                    <xsl:for-each select="passseg_to_passengers/passseg_to_passenger">
                        <td width="50">
                            <xsl:value-of select="Prop[@prop_name = 'carryonbagcount']/@val" />
                        </td>
                    </xsl:for-each>
                </tr>
            </table>                            
        </td>
        <td style="text-align: left;" width="100">
            <table style="text-align: left; line-height: 18px; font-family: Arial, Helvetica, sans-serif; font-size: 12px; color:#333333;" width="100">
                <tr>
                    <xsl:for-each select="passseg_to_passengers/passseg_to_passenger">
                        <td width="50">
                            <xsl:value-of select="Prop[@prop_name = 'checkedbagcount']/@val" />
                        </td>
                    </xsl:for-each>
                </tr>
            </table>                            
        </td>
    </xsl:template>

</xsl:stylesheet>
4

2 回答 2

1

假设输出的carryonbagcount 应该是每条腿的最大值,这里是对蒂姆答案的一个小调整。

这个输入文件...

<passenger>
  <passengersegment>
      <journeynumber>0</journeynumber>
      <segmentnumber>0</segmentnumber>
      <carryonbagcount>1</carryonbagcount>
      <checkedbagcount>1</checkedbagcount>
  </passengersegment>
  <passengersegment>
       <journeynumber>0</journeynumber>
       <segmentnumber>1</segmentnumber>
       <carryonbagcount>1</carryonbagcount>
       <checkedbagcount>1</checkedbagcount>
   </passengersegment>
   <passengersegment>
       <journeynumber>1</journeynumber>
       <segmentnumber>0</segmentnumber>
       <carryonbagcount>1</carryonbagcount>
       <checkedbagcount>1</checkedbagcount>
   </passengersegment>
   <passengersegment>
       <journeynumber>1</journeynumber>
       <segmentnumber>1</segmentnumber>
       <carryonbagcount>1</carryonbagcount>
       <checkedbagcount>1</checkedbagcount>
   </passengersegment>

...当此 XSLT 1.0 样式表应用于它时...

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="html" doctype-system="about:legacy-compat" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />

<xsl:key name="kJourney" match="passengersegment" use="journeynumber" />  

<xsl:template match="/*">
<table>
 <thead>
  <tr>
   <th><strong>Journey</strong></th> <th><strong>CARRY-ON</strong></th> <th><strong>CHECKED</strong></th>
  </tr>
 </thead>
 <tbody>
    <xsl:apply-templates select="passengersegment[generate-id() =
                                                  generate-id(key('kJourney',journeynumber)[1])]"
                         mode="group" /> 
 </tbody>
</table>
</xsl:template>

<xsl:template match="passengersegment" mode="group">
  <tr>
    <td><xsl:value-of select="journeynumber" /></td>

    <xsl:apply-templates select="." mode="max"> 
      <xsl:with-param name="col-name" select="'carryonbagcount'" />
    </xsl:apply-templates>

    <xsl:apply-templates select="." mode="max"> 
      <xsl:with-param name="col-name" select="'checkedbagcount'" />
    </xsl:apply-templates>
  </tr>  
</xsl:template>

<xsl:template match="passengersegment" mode="max"> 
  <xsl:param name="col-name" /> 
  <xsl:for-each select="key('kJourney',journeynumber)/*[name()=$col-name]">
    <xsl:sort select="." data-type="number" order="descending" />
    <xsl:if test="position()=1">
      <td><xsl:value-of select="." /></td>
    </xsl:if>
  </xsl:for-each>  
</xsl:template>  

</xsl:stylesheet>

...产生此 HTML 输出...

<!DOCTYPE html SYSTEM "about:legacy-compat">
<table>
  <thead>
    <tr>
      <th><strong>Journey</strong></th>
      <th><strong>CARRY-ON</strong></th>
      <th><strong>CHECKED</strong></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>0</td>
      <td>1</td>
      <td>1</td>
    </tr>
    <tr>
      <td>1</td>
      <td>1</td>
      <td>1</td>
    </tr>
  </tbody>
</table>

更新

到目前为止,OP已经更改了问题和样本数据,这确实是一个新问题。假设@entity_id唯一标识一个乘客。如果不是,OP 应该正确解释输入数据结构和转换规则。所以这是新问题的解决方案..

这个 XSLT 1.0 样式表...

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="html" doctype-system="about:legacy-compat" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />

<xsl:key name="kJourney" match="passseg_to_passenger"
  use="concat( ../../Prop/@entity_id, '|', Prop[@prop_name='journeynumber']/@val)" /> 
  <!-- Assume that @entity_id is an identifier for the passenger. -->

<xsl:template match="bookingcontact_to_booking">
<table>
 <thead>
  <tr>
   <th><strong>PASSENGER</strong></th> <th><strong>CARRY-ON</strong></th> <th><strong>CHECKED</strong></th>
  </tr>
 </thead>
 <tbody>
   <xsl:apply-templates select="passenger_to_bookings/passenger_to_booking" /> 
 </tbody>
</table>
</xsl:template>

<xsl:template match="passenger_to_booking">
  <xsl:variable name="passenger-id" select="(Prop/@entity_id)[1]" />
  <xsl:variable name="passenger-name" select="
   concat( Prop[@prop_name='firstname']/@val, ' ', Prop[@prop_name='lastname']/@val)" />
  <tr>
   <xsl:apply-templates select="passseg_to_passengers/passseg_to_passenger
       [generate-id() = generate-id(key('kJourney',
            concat( $passenger-id, '|', Prop[@prop_name='journeynumber']/@val))[1])]"
     mode="group"> 
    <xsl:with-param name="passenger-id"   select="$passenger-id" />
    <xsl:with-param name="passenger-name" select="$passenger-name" />
  </xsl:apply-templates>   
  </tr>
</xsl:template>

<xsl:template match="passseg_to_passenger" mode="group">
  <xsl:param name="passenger-id" />
  <xsl:param name="passenger-name" />
  <td><xsl:value-of select="$passenger-name" /></td>

  <xsl:apply-templates select="." mode="max"> 
    <xsl:with-param name="passenger-id" select="$passenger-id" />
    <xsl:with-param name="col-name" select="'carryonbagcount'" />
  </xsl:apply-templates>

  <xsl:apply-templates select="." mode="max"> 
    <xsl:with-param name="passenger-id" select="$passenger-id" />
    <xsl:with-param name="col-name" select="'checkedbagcount'" />
  </xsl:apply-templates>
</xsl:template>

<xsl:template match="passseg_to_passenger" mode="max"> 
  <xsl:param name="passenger-id" />
  <xsl:param name="col-name" /> 
  <xsl:for-each select="key('kJourney',
      concat( $passenger-id, '|', Prop[@prop_name='journeynumber']/@val)
  )/Prop[@prop_name=$col-name]/@val">
    <xsl:sort select="." data-type="number" order="descending" />
    <xsl:if test="position()=1">
      <td><xsl:value-of select="." /></td>
    </xsl:if>
  </xsl:for-each>  
</xsl:template>  

</xsl:stylesheet>

...当应用于此输入文档时...

<bookingcontact_to_booking>
    <passenger_to_bookings> 
        <passenger_to_booking>
            <Prop pk_id="4147" entity_id="126" val="SMITH" type_id="20" prop_name="lastname" prop_id="10208"/>
            <Prop pk_id="4147" entity_id="126" val="PEDRO" type_id="20" prop_name="firstname" prop_id="10206"/>
            <passseg_to_passengers>
                <passseg_to_passenger>
                    <Prop pk_id="9432" entity_id="122" val="2013-08-27 17:45:00.000" type_id="30" prop_name="arrivaltime" prop_id="10216"/>
                    <Prop pk_id="9432" entity_id="122" val="188" type_id="20" prop_name="flightnumber" prop_id="10217"/>
                    <Prop pk_id="9432" entity_id="122" val="5" type_id="10" prop_name="checkedbagcount" prop_id="10220"/>
                    <Prop pk_id="9432" entity_id="122" val="1" type_id="10" prop_name="carryonbagcount" prop_id="10221"/>
                    <Prop pk_id="9432" entity_id="122" val="1" type_id="10" prop_name="journeynumber" prop_id="10222"/>
                    <Prop pk_id="9432" entity_id="122" val="0" type_id="10" prop_name="segmentnumber" prop_id="10223"/>
                    <Prop pk_id="9432" entity_id="122" val="2013-08-27 08:12:00.000" type_id="30" prop_name="departuretime" prop_id="10296"/>
                    <Prop pk_id="9432" entity_id="122" val="Las Vegas, NV" type_id="20" prop_name="departureairport" prop_id="10297"/>
                    <Prop pk_id="9432" entity_id="122" val="New York, NY - LaGuardia " type_id="20" prop_name="arrivalairport" prop_id="10298"/>
                    <Prop pk_id="9432" entity_id="122" val="10B,20B" type_id="20" prop_name="seatassignment" prop_id="10299"/>
                </passseg_to_passenger>
                <passseg_to_passenger>
                    <Prop pk_id="9433" entity_id="122" val="10B,20B" type_id="20" prop_name="seatassignment" prop_id="10299"/>
                    <Prop pk_id="9433" entity_id="122" val="Fort Lauderdale, FL" type_id="20" prop_name="arrivalairport" prop_id="10298"/>
                    <Prop pk_id="9433" entity_id="122" val="New York, NY - LaGuardia " type_id="20" prop_name="departureairport" prop_id="10297"/>
                    <Prop pk_id="9433" entity_id="122" val="2013-08-27 19:45:00.000" type_id="30" prop_name="departuretime" prop_id="10296"/>
                    <Prop pk_id="9433" entity_id="122" val="1" type_id="10" prop_name="segmentnumber" prop_id="10223"/>
                    <Prop pk_id="9433" entity_id="122" val="1" type_id="10" prop_name="journeynumber" prop_id="10222"/>
                    <Prop pk_id="9433" entity_id="122" val="1" type_id="10" prop_name="carryonbagcount" prop_id="10221"/>
                    <Prop pk_id="9433" entity_id="122" val="5" type_id="10" prop_name="checkedbagcount" prop_id="10220"/>
                    <Prop pk_id="9433" entity_id="122" val="779" type_id="20" prop_name="flightnumber" prop_id="10217"/>
                    <Prop pk_id="9433" entity_id="122" val="2013-08-27 22:45:00.000" type_id="30" prop_name="arrivaltime" prop_id="10216"/>
                </passseg_to_passenger>
            </passseg_to_passengers>
        </passenger_to_booking>
    </passenger_to_bookings>
</bookingcontact_to_booking>

...产生此 html 输出文档...

<!DOCTYPE html SYSTEM "about:legacy-compat">
<table>
  <thead>
    <tr>
      <th><strong>PASSENGER</strong></th>
      <th><strong>CARRY-ON</strong></th>
      <th><strong>CHECKED</strong></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>PEDRO SMITH</td>
      <td>1</td>
      <td>5</td>
    </tr>
  </tbody>
</table>
于 2013-08-09T08:39:03.830 回答
1

在没有看到预期 HTML 样本的情况下给出准确答案有点棘手,而且还因为 XSLT 中的元素名称似乎与输入 XML 样本不匹配。但是,您需要在这里阅读和使用的技术是Muenchian Grouping。这是在 XSLT 1.0 中对元素进行分组的最有效方式。

在您的情况下,您希望为乘客获取不同的旅程,然后为每个人获取第一段。为此,您可以定义一个键来按旅程编号查找乘客段元素

<xsl:key name="journey" match="passengersegment" use="journeynumber"/>

然后,为了获得不同的旅程编号,您查看所有乘客段,但只选择在给定旅程编号值的键中首先出现的那些。

<xsl:apply-templates 
     select="passengersegment
             [generate-id() = generate-id(key('journey', journeynumber)[1])]"/>

在匹配乘客段的模板中,您可以输出该段的第一个carryonbagcountcheckednbagcount(旅程中的第一个)。

试试这个 XSLT 作为开始,并以此为基础:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:key name="journey" match="passengersegment" use="journeynumber"/>

  <xsl:template match="/passenger">
    <table border="1">
      <tr>
        <th>Journey</th>
        <th>Carry on</th>
        <th>Checked</th>
      </tr>
      <xsl:apply-templates select="passengersegment[generate-id() = generate-id(key('journey', journeynumber)[1])]"/>
    </table>
  </xsl:template>

  <xsl:template match="passengersegment">
    <tr>
      <td>
        <xsl:value-of select="journeynumber"/>
      </td>
      <td>
        <xsl:value-of select="carryonbagcount"/>
      </td>
      <td>
        <xsl:value-of select="checkedbagcount"/>
      </td>
    </tr>
  </xsl:template>
</xsl:stylesheet>

请注意,如果想要获取旅程中所有航段的总携带行李数,那么在乘客航段中,您可以执行以下操作:

<xsl:value-of select="sum(key('journey', journeynumber)/carryonbagcount)" />
于 2013-08-09T07:56:14.280 回答