类似重复保持标签的XSLT迭代

时间:2014-01-01 10:30:08

标签: xml xslt transform

我有一个xml,看起来像:

<RestrictedTicket>abc</RestrictedTicket> 
<FlightDetails1>
  <CouponNumber>1</CouponNumber> 
  <ServiceClass>F</ServiceClass> 
  <CarrierCode>SL</CarrierCode> 
</FlightDetails1>
<FlightDetails2>
  <CouponNumber>2</CouponNumber> 
  <ServiceClass>G</ServiceClass> 
  <CarrierCode>KL</CarrierCode> 
</FlightDetails2>

我使用的XSLT看起来像:

<RestrictedTicket>
<xsl:value-of select="RestrictedTicket" />
</RestrictedTicket>
<xsl:for-each select="FlightDetails1">
<FlightDetails>
<CouponNumber>
<xsl:value-of select="CouponNumber" />
</CouponNumber>
<ServiceClass>
<xsl:value-of select="ServiceClass" />
</ServiceClass>
<CarrierCode>
<xsl:value-of select="CarrierCode" />
</CarrierCode>
</FlightDetails>
</xsl:for-each>

转换后生成的输出xml应如下所示:

<RestrictedTicket>abc</RestrictedTicket> 
    <FlightDetails>
      <CouponNumber>1</CouponNumber> 
      <ServiceClass>F</ServiceClass> 
      <CarrierCode>SL</CarrierCode> 
    </FlightDetails>
    <FlightDetails>
      <CouponNumber>2</CouponNumber> 
      <ServiceClass>G</ServiceClass> 
      <CarrierCode>KL</CarrierCode> 
    </FlightDetails>

我不能在这里使用复制功能,因为我正在进行许多值之间的转换。我要做的是重复使用FlightDetails的代码,这样我就不需要写8次了(FlightDetails有8个重复标签,例如FlightDetails1,FlightDetails2 ...... FlightDetails8有类似的子标签)。目标是将持有标签从FlightDetails1更改为FlightDetails,并避免为8个flightdetails数据写入相同的代码8次。

2 个答案:

答案 0 :(得分:2)

您正在寻找的表达式,它将选择 FlightDetail1 FlightDetail2 (等等)元素:

<xsl:for-each select="*[starts-with(local-name(), 'FlightDetails')]">

但是,你提到重用代码,所以值得一提的是你应该使用XSLT Identity Transform来解决这个问题。

<xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>

单独复制所有节点而不做任何更改。但是,这意味着您需要做的就是为要匹配的节点添加模板。因此,您不会使用 xsl:for-each ,而是使用模板匹配。

 <xsl:template match="*[starts-with(local-name(), 'FlightDetails')]">

试试这个XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="@*|node()">
      <xsl:copy>
         <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
   </xsl:template>

   <xsl:template match="*[starts-with(local-name(), 'FlightDetails')]">
      <FlightDetails>
         <xsl:apply-templates select="@*|node()"/>
      </FlightDetails>
   </xsl:template>
</xsl:stylesheet>

应用于以下XML

<Tickets>
   <RestrictedTicket>abc</RestrictedTicket>
   <FlightDetails1>
      <CouponNumber>1</CouponNumber>
      <ServiceClass>F</ServiceClass>
      <CarrierCode>SL</CarrierCode>
   </FlightDetails1>
   <FlightDetails2>
      <CouponNumber>2</CouponNumber>
      <ServiceClass>G</ServiceClass>
      <CarrierCode>KL</CarrierCode>
   </FlightDetails2>
</Tickets>

以下是输出

<Tickets>
   <RestrictedTicket>abc</RestrictedTicket>
   <FlightDetails>
      <CouponNumber>1</CouponNumber>
      <ServiceClass>F</ServiceClass>
      <CarrierCode>SL</CarrierCode>
   </FlightDetails>
   <FlightDetails>
      <CouponNumber>2</CouponNumber>
      <ServiceClass>G</ServiceClass>
      <CarrierCode>KL</CarrierCode>
   </FlightDetails>
</Tickets>

例如,了解如何编写用于复制 CouponNumber ServiceClass 的任何显式代码。这是通过使用模板<xsl:template match="@*|node()">实现的,因此重要的是此模板存在于XSLT中。

答案 1 :(得分:0)

感谢您的帮助。我修改了for-each,现在它完美无缺。修改后的xslt使用:

<xsl:for-each select="*[starts-with(local-name(), 'FlightDetails')]">

而不是<xsl:for-each select="FlightDetails1">.

其余代码保持不变。再次感谢您的帮助。