Search code examples
xmlxsltxslt-2.0

Have to remove element without child element from XML


We have input XML .in that, Loop element is StockLine tag .but when it repeats it also creates empty sub element comment inside Comment Line tag.

Let's say we have 2 stocklines.we have exactly 2 commentLine tag. this two commentLine tag is unused. want to remove from XML. But at the same time CommentLine with comments should not be deleted. Only CommentLine with no Comment should be deleted.

Basically, We wanted to remove this portion :

<CommentLine>
            <OrderLineID>OR-1593605</OrderLineID>
         </CommentLine>

INPUT XML:

<?xml version="1.0" encoding="Windows-1252"?>
<SalesOrders xmlns:xsd="http://www.w3.org/2001/XMLSchema-instance"
             xsd:noNamespaceSchemaLocation="SDOC.XSD">
   <Orders>
      <OrderHeader>
      <Customer>0TARGT</Customer>
     </OrderHeader>
      <OrderDetails>
         <StockLine>
            <CustomerPoLine>9999</CustomerPoLine>
            <StockCode>xyz</StockCode>
            <StockDescription>xyz desc</StockDescription>
            <OrderQty>10.0</OrderQty>
            <OrderUom>CS</OrderUom>
            <Price>93.48</Price>
            <PriceUom>CS</PriceUom>
            <AlwaysUsePriceEntered>Y</AlwaysUsePriceEntered>
            <UserDefined>1</UserDefined>
            <OrderLineID>OR-1593605</OrderLineID>
         </StockLine>
         <CommentLine>
            <OrderLineID>OR-1593605</OrderLineID>
         </CommentLine>
         <CommentLine>
            <Comment>TEST PURPOSE</Comment>
            <OrderLineID>OR-1810120</OrderLineID>
         </CommentLine>
         <CommentLine>
            <Comment>This is for test purpose</Comment>
            <OrderLineID>OR-1810121</OrderLineID>
         </CommentLine>
         <CommentLine>
            <Comment>EDI-TEST</Comment>
            <OrderLineID>OR-1810123</OrderLineID>
         </CommentLine>
      </OrderDetails>
   </Orders>
</SalesOrders>

We tried following XSLT :

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" encoding="Windows-1252" indent="yes"/>

        <xsl:template match="@xsi:nil[.='true']" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
    <xsl:template match="@*|node()">
        <xsl:copy copy-namespaces="no">
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    </xsl:stylesheet>

Expected Output :

<?xml version="1.0" encoding="Windows-1252"?>
    <SalesOrders xmlns:xsd="http://www.w3.org/2001/XMLSchema-instance"
                 xsd:noNamespaceSchemaLocation="SDOC.XSD">
       <Orders>
          <OrderHeader>
          <Customer>0TARGT</Customer>
         </OrderHeader>
          <OrderDetails>
             <StockLine>
                <CustomerPoLine>9999</CustomerPoLine>
                <StockCode>xyz</StockCode>
                <StockDescription>xyz desc</StockDescription>
                <OrderQty>10.0</OrderQty>
                <OrderUom>CS</OrderUom>
                <Price>93.48</Price>
                <PriceUom>CS</PriceUom>
                <AlwaysUsePriceEntered>Y</AlwaysUsePriceEntered>
                <UserDefined>1</UserDefined>
                <OrderLineID>OR-1593605</OrderLineID>
             </StockLine>
             <CommentLine>
                <Comment>TEST PURPOSE</Comment>
                <OrderLineID>OR-1810120</OrderLineID>
             </CommentLine>
             <CommentLine>
                <Comment>This is for test purpose</Comment>
                <OrderLineID>OR-1810121</OrderLineID>
             </CommentLine>
             <CommentLine>
                <Comment>EDI-TEST</Comment>
                <OrderLineID>OR-1810123</OrderLineID>
             </CommentLine>
          </OrderDetails>
       </Orders>
    </SalesOrders>

Solution

  • If you want to remove all CommentLine elements not having a Comment child then add a template <xsl:template match="CommentLine[not(Comment)]"/>.

    If you want to remove only the CommentLine with an OrderLineID in the StockLine sibling then add a template <xsl:template match="CommentLine[OrderLineID = preceding-sibling::StockLine/OrderLineID and not(Comment)]"/>.