eMi
eMi

Reputation: 5628

Remove Node after foreach walkthrough

I have this XML:

<ProdOrders>
  <ProdOrder>
    <Id>20</Id>
    <ProdOrderNo>1107939.001</ProdOrderNo>
    <ChargeNumbers>
      <ChargeNo>C_1_1107939.001</ChargeNo>
      <ChargeNo>C_2_1107939.001</ChargeNo>
      <ChargeNo>C_3_1107939.001</ChargeNo>
      <ChargeNo>C_4_1107939.001</ChargeNo>
      <ChargeNo>C_5_1107939.001</ChargeNo>
      <ChargeNo>C_6_1107939.001</ChargeNo>
    </ChargeNumbers>
  </ProdOrder>
</ProdOrders>

In the XSLT there is a for-each loop. Is it possible to delete/remove the actual last node which was just used in the for-each loop and continue with the next until all of them are removed?

<xsl:template match="ProdOrders">
  <xsl:for-each select="ProdOrder">
     <xsl:for-each select="ChargeNumbers/ChargeNo">
        <!-- Do something with the ChargeNo Value -->
        <!-- Now delete the Node <ChargeNo> with its value and continue for-each loop -->
     </xsl:for-each>
  </xsl:for-each>

So the XML would change to:

 <ProdOrders>
  <ProdOrder>
    <Id>20</Id>
    <ProdOrderNo>1107939.001</ProdOrderNo>
    <ChargeNumbers>
      <ChargeNo>C_2_1107939.001</ChargeNo>
      <ChargeNo>C_3_1107939.001</ChargeNo>
      <ChargeNo>C_4_1107939.001</ChargeNo>
      <ChargeNo>C_5_1107939.001</ChargeNo>
      <ChargeNo>C_6_1107939.001</ChargeNo>
    </ChargeNumbers>
  </ProdOrder>
</ProdOrders>

And in the for-each loop the first treated item would be <ChargeNo>C_2_1107939.001</ChargeNo>

I'm kinda new to Xsl/-t and I don't even know if this is possible to do or what alternatives I'd have.

Upvotes: 0

Views: 325

Answers (2)

michael.hor257k
michael.hor257k

Reputation: 117100

I don't see that you are doing anything with the discarded value before you get rid of it. The result you show could be achieved much more simply as:

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

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

<!-- suppress the first ChargeNo -->    
<xsl:template match="ChargeNo[1]"/>

</xsl:stylesheet>

Upvotes: 1

Joel M. Lamsen
Joel M. Lamsen

Reputation: 7173

The stylesheet below:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output indent="yes" omit-xml-declaration="yes"/>
    <xsl:strip-space elements="*"/>

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

    <xsl:template match="ChargeNo">
        <xsl:choose>
            <!-- alternatively, you can choose position() = 1, for the first occurrence -->
            <xsl:when test="position()=last()"/>
            <xsl:otherwise>
                <xsl:copy>
                    <xsl:value-of select="concat(., '-test')"/>
                </xsl:copy>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

</xsl:stylesheet>

when applied to you input XML, produces:

<ProdOrders>
   <ProdOrder>
      <Id>20</Id>
      <ProdOrderNo>1107939.001</ProdOrderNo>
      <ChargeNumbers>
         <ChargeNo>C_1_1107939.001-test</ChargeNo>
         <ChargeNo>C_2_1107939.001-test</ChargeNo>
         <ChargeNo>C_3_1107939.001-test</ChargeNo>
         <ChargeNo>C_4_1107939.001-test</ChargeNo>
         <ChargeNo>C_5_1107939.001-test</ChargeNo>
      </ChargeNumbers>
   </ProdOrder>
</ProdOrders>

Upvotes: 0

Related Questions