0

I have to add Element Main/Years/Year/Notification/@UniqueId="27" & Main/Years/Year/@IsFailFlag = "Y" , Only if Main/Years/Year/Month/Extn/@Flag !=''. and I have to copy Main/Years/Year/Month for such cases.

XML
<?xml version="1.0" encoding="UTF-8"?>
<Main>
   <Years>
      <Year>
         <Month ActualDate="" Type="C" FailText="">
            <Extn Flag="A" />
            <Details>
               <Line A="a" B="3" C="1" />
            </Details>
         </Month>
         <Month ActualDate="" Type="C" FailText="">
            <Extn Flag="B" />
            <Details>
               <Line A="a" B="3" C="1" />
            </Details>
         </Month>
         <Month ActualDate="" Type="C" FailText="">
            <Extn Flag="" />
            <Details>
               <Line A="a" B="3" C="1" />
            </Details>
         </Month>
      </Year>
   </Years>
</Main>

My XSL

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
   <xsl:output method="xml" indent="yes" />
   <xsl:strip-space elements="*" />
   <xsl:template match="/">
      <LoadShipment>
         <xsl:for-each select="/Main/Years/Year/Month/Extn">
            <xsl:if test="@Flag != ''">
               <xsl:attribute name="IsFailFlag">
                  <xsl:value-of select="'Y'" />
               </xsl:attribute>
               <Notification>
                  <xsl:attribute name="UniqueId">
                     <xsl:value-of select="'27'" />
                  </xsl:attribute>
               </Notification>
               <xsl:copy-of select=".." />
            </xsl:if>
         </xsl:for-each>
      </LoadShipment>
   </xsl:template>
</xsl:stylesheet>

I am getting repeated Notification as its inside for loop and i cant move it out becuase then it will always get populated irrespective of the condition

Output

<?xml version="1.0" encoding="UTF-8"?>
<LoadShipment IsFailFlag="Y">
   <Notification UniqueId="27" />
   <Month ActualDate="" Type="C" FailText="">
      <Extn Flag="A" />
      <Details>
         <Line A="a" B="3" C="1" />
      </Details>
   </Month>
   <Notification UniqueId="27" />
   <Month ActualDate="" Type="C" FailText="">
      <Extn Flag="B" />
      <Details>
         <Line A="a" B="3" C="1" />
      </Details>
   </Month>
</LoadShipment>

Expected Output

<?xml version="1.0" encoding="UTF-8"?>
<LoadShipment IsFailFlag="Y">
   <Notification UniqueId="27" />
   <Month ActualDate="" Type="C" FailText="">
      <Extn Flag="A" />
      <Details>
         <Line A="a" B="3" C="1" />
      </Details>
   </Month>
    <Month ActualDate="" Type="C" FailText="">
      <Extn Flag="B" />
      <Details>
         <Line A="a" B="3" C="1" />
      </Details>
   </Month>
</LoadShipment>

1 Answer 1

1

How's this:

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

  <xsl:template match="/">
    <xsl:variable name="badMonths"
                  select="Main/Years/Year/Month[Extn/@Flag != '']" />

    <LoadShipment>
      <xsl:if test="$badMonths">
        <xsl:attribute name="IsFailFlag">Y</xsl:attribute>
        <Notification UniqueId="27" />

        <xsl:copy-of select="$badMonths" />
      </xsl:if>
    </LoadShipment>
  </xsl:template>

</xsl:stylesheet>

When run on your sample input, the result is:

<LoadShipment IsFailFlag="Y">
  <Notification UniqueId="27" />
  <Month ActualDate="" Type="C" FailText="">
    <Extn Flag="A" />
    <Details>
      <Line A="a" B="3" C="1" />
    </Details>
  </Month>
  <Month ActualDate="" Type="C" FailText="">
    <Extn Flag="B" />
    <Details>
      <Line A="a" B="3" C="1" />
    </Details>
  </Month>
</LoadShipment>

Or a different approach that's a little more "XSLT-esque" (same result):

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

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

  <xsl:template match="/*">
    <xsl:variable name="badMonths"
                  select="Years/Year/Month[Extn/@Flag != '']" />

    <LoadShipment>
      <xsl:apply-templates select="(.)[$badMonths]" mode="failed" />
      <xsl:apply-templates select="$badMonths" />
    </LoadShipment>
  </xsl:template>

  <xsl:template match="*" mode="failed">
    <xsl:attribute name="IsFailFlag">Y</xsl:attribute>
    <Notification UniqueId="27" />
  </xsl:template>

</xsl:stylesheet>
Sign up to request clarification or add additional context in comments.

1 Comment

I am going with your first solution.Its easier to understand.Also can you provide url where can can learn xslt.I know basic stuff

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.