Frage

I am trying to normalise a piece of xml. I am having trouble with the section relating to ProductID. I am trying to creatre a container for it <products><productid>xyz</productid></products> by my <xsl:for-each select="ProductID"> does not seem to be working. Can anyone point me in the right direction?

<Batch>
  <Promotion>
    <PromotionID>000873</PromotionID>
    <Description country="GB" language="en" variant="">*P* Free Clotted Cream      Scone</Description>
    <MultibuyGroup>
        <RewardType>1</RewardType>
        <RewardValue>0.0</RewardValue>
        <RewardValue currency="GBP">1.0</RewardValue>
        <ProductID>1300003536</ProductID>
        <ProductID>1300000746</ProductID>
        <ProductID>1300002393</ProductID>
        <ProductID>1300002648</ProductID>
        <ProductID>1300002899</ProductID>
        <ProductID>1300003535</ProductID>
        <ProductID>1300003222</ProductID>
    </MultibuyGroup>
    <MultibuyGroup>
        <RewardType>0</RewardType><RewardValue>0.0</RewardValue>
        <RewardValue currency="GBP">0.0</RewardValue>
        <ProductID>1570000102</ProductID>
    </MultibuyGroup>
    <Timetable>
      <SartDate>2008-02-02T00:00:00+00:00</StartDate>
      <FinishDate>2008-02-03T23:59:59+00:00</FinishDate>
    </Timetable>
 </Promotion>
</Batch>

I am trying to get it to look like.

<Batch>
  <Promotion>
    <PromotionID>000873</PromotionID>
    <badge_id>tbc</badge_id>
    <loyaltyaccountholdersonly>TBC</loyaltyaccountholdersonly>
    <locations>TBC</locations>
    <Description country="GB" language="en" variant="">*P* Free Clotted Cream      Scone</Description>
    <MultibuyGroup>
        <RewardType>1</RewardType>
        <RewardValue>0.0</RewardValue>
        <RewardValue currency="GBP">1.0</RewardValue>
        <products>
          <ProductID>1300003536</ProductID>
          <ProductID>1300000746</ProductID>
          <ProductID>1300002393</ProductID>
          <ProductID>1300002648</ProductID>
          <ProductID>1300002899</ProductID>
          <ProductID>1300003535</ProductID>
          <ProductID>1300003222</ProductID>
        </products>
    </MultibuyGroup>
    <MultibuyGroup>
        <RewardType>0</RewardType><RewardValue>0.0</RewardValue>
        <RewardValue currency="GBP">0.0</RewardValue>
        <ProductID>1570000102</ProductID>
    </MultibuyGroup>
    <Timetable>
      <SartDate>2008-02-02T00:00:00+00:00</StartDate>
      <FinishDate>2008-02-03T23:59:59+00:00</FinishDate>
    </Timetable>
 </Promotion>
</Batch>

Using the following XSL

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">  
<promotions> 
<xsl:for-each select="Batch/Promotion">  
  <promotion>
    <promotion_id><xsl:value-of select="PromotionID"/></promotion_id>    
    <badge_id>TBC</badge_id>
    <loyaltyaccountholdersonly>TBC</loyaltyaccountholdersonly>
    <description><xsl:value-of select="Description[@country = 'GB']"/></description>
    <locations>TBC</locations>
    <xsl:for-each select="MultibuyGroup">
      <multibuygroup>
        <products>
        <xsl:for-each select="ProductID">
          <product_id><xsl:value-of select="ProductID"/></product_id>
        </xsl:for-each>
        </products>
        <rewardtype><xsl:value-of select="RewardType"/></rewardtype> 
        <rewardvalue><xsl:value-of select="RewardValue"/></rewardvalue>
        <rewardthreshold>TBC</rewardthreshold>
        <groupdescription><xsl:value-of select="GroupDescription"/></groupdescription>
      </multibuygroup>
    </xsl:for-each>
    <timetable> 
      <startdate><xsl:value-of select="Timetable/StartDate"/></startdate>
      <expirydate><xsl:value-of select="Timetable/FinishDate"/></expirydate>
    </timetable>
  </promotion>
</xsl:for-each>   
</promotions>
</xsl:template>
</xsl:stylesheet>
War es hilfreich?

Lösung

Your XML is not correct (element opening SartDate instead of StartDate). In your attempt it seems to me you're forgetting that XML is case sensitive. If you want to have a PromotionID in your output, there's no way it will happen if you put promotion_id as the element name in the XSLT.

Anyway.

Here's an XSLT that does what I think you are asking for:

  1. It first asks to generally copy all elements, including attributes.
  2. Then it asks to add a few elements to each Promotion element.
  3. Then for the Multibuy stuff, it asks to copy the list of products.
  4. And finally it asks not to copy (again) the ProductID elements at their original place.

Yves

<?xml-stylesheet type="text/xsl"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="*">  
    <xsl:copy>
        <xsl:copy-of select="@*" />
        <xsl:apply-templates />
    </xsl:copy>
</xsl:template>
<xsl:template match="Promotion">  
    <xsl:copy>
        <badge_id>tbc</badge_id>
        <loyaltyaccountholdersonly>TBC</loyaltyaccountholdersonly>
        <locations>TBC</locations>
        <xsl:copy-of select="@*" />
        <xsl:apply-templates />
    </xsl:copy>
</xsl:template>
<xsl:template match="MultibuyGroup">  
    <xsl:copy>
        <xsl:copy-of select="@*" />

        <xsl:apply-templates />
        <Products>
            <xsl:for-each select="ProductID">
                <xsl:copy>
                    <xsl:copy-of select="@*" />
                    <xsl:apply-templates />
                </xsl:copy>
            </xsl:for-each>
        </Products>
    </xsl:copy>
</xsl:template>   
<xsl:template match="ProductID"></xsl:template>
</xsl:stylesheet>
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top