Search code examples
xmlxsltxslt-2.0

XSLT : How do i assign Constant value using XML element


We have input XML. In that,We tried to put constant value using <LineActionType> element.

We basically want to add <LineActionType >A<LineActionType /> this element constant value on each Comment Line Tag. that is

 <CommentLine>
                    <Comment>Comment#1</Comment>
                    <OrderLineID>OR-1810143</OrderLineID>
                    <UserDefined>3</UserDefined>
                    <LineActionType >A<LineActionType />
                 </CommentLine>

Input XML

<?xml version="1.0" encoding="UTF-8"?>
<SalesOrders xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsd="http://www.w3.org/2001/XMLSchema-instance" xsd:noNamespaceSchemaLocation="SORTOIDOC.XSD">
   <Orders>
      <OrderHeader>
         <CustomerPoNumber>Manual Order 1</CustomerPoNumber>
         <OrderActionType>A</OrderActionType>
      </OrderHeader>
      <OrderDetails>
         <StockLine>
            <CustomerPoLine>9999</CustomerPoLine>
            <StockCode>abc-1</StockCode>
            <StockDescription>ASSEMBLED</StockDescription>
            <OrderQty>2.0</OrderQty>
            <OrderUom>EA</OrderUom>
            <PriceUom>EA</PriceUom>
            <AlwaysUsePriceEntered>Y</AlwaysUsePriceEntered>
            <UserDefined>1</UserDefined>
            <OrderLineID>OR-1810141</OrderLineID>
         </StockLine>
         <StockLine>
            <CustomerPoLine>9999</CustomerPoLine>
            <StockCode>FBX-SMO30029-8</StockCode>
            <StockDescription>TARGET SOAP PDQ 2014 ASSEMBLED</StockDescription>
            <OrderQty>3.0</OrderQty>
            <OrderUom>EA</OrderUom>
            <PriceUom>EA</PriceUom>
            <AlwaysUsePriceEntered>Y</AlwaysUsePriceEntered>
            <UserDefined>2</UserDefined>
            <OrderLineID>OR-1810142</OrderLineID>
         </StockLine>
         <CommentLine>
            <Comment>Comment#1</Comment>
            <OrderLineID>OR-1810143</OrderLineID>
            <UserDefined>3</UserDefined>
            <LineActionType />
         </CommentLine>
         <CommentLine>
            <Comment>Comment#2</Comment>
            <OrderLineID>OR-1810144</OrderLineID>
            <UserDefined>4</UserDefined>
            <LineActionType />
         </CommentLine>
      </OrderDetails>
   </Orders>
</SalesOrders>

We tried following XSLT 2.0:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0">
   <xsl:output method="xml" encoding="Windows-1252" indent="yes" />
   <xsl:template match="@*|node()">
      <xsl:copy>
         <xsl:apply-templates select="@*|node()" />
      </xsl:copy>
   </xsl:template>
   <xsl:template match="OrderDetails">
      <xsl:copy>
         <xsl:apply-templates select="*">
            <xsl:sort select="xs:integer(UserDefined)" />
         </xsl:apply-templates>
      </xsl:copy>
   </xsl:template>
   <xsl:template match="StockLine[not(StockCodeDescription) and not (OrderQty) and not(Price)]">
      <CommentLine>
         <Comment>
            <xsl:value-of select="StockCode" />
         </Comment>
         <xsl:copy-of select="OrderLineID" />
         <xsl:copy-of select="UserDefined" />
        </CommentLine>
   </xsl:template>
   <xsl:template match="CommentLine[OrderLineID = preceding-sibling::StockLine/OrderLineID and not(Comment)]" />
   <xsl:template match="CommentLine[some $sib in preceding-sibling::CommentLine satisfies deep-equal(., $sib)]" />
</xsl:stylesheet>

EXPECTED OUTPUT :

<?xml version="1.0" encoding="UTF-8"?>
<SalesOrders xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsd="http://www.w3.org/2001/XMLSchema-instance" xsd:noNamespaceSchemaLocation="SORTOIDOC.XSD">
   <Orders>
      <OrderHeader>
         <CustomerPoNumber>Manual Order 1</CustomerPoNumber>
         <OrderActionType>A</OrderActionType>
      </OrderHeader>
      <OrderDetails>
         <StockLine>
            <CustomerPoLine>9999</CustomerPoLine>
            <StockCode>abc-1</StockCode>
            <StockDescription>ASSEMBLED</StockDescription>
            <OrderQty>2.0</OrderQty>
            <OrderUom>EA</OrderUom>
            <PriceUom>EA</PriceUom>
            <AlwaysUsePriceEntered>Y</AlwaysUsePriceEntered>
            <UserDefined>1</UserDefined>
            <OrderLineID>OR-1810141</OrderLineID>
         </StockLine>
         <StockLine>
            <CustomerPoLine>9999</CustomerPoLine>
            <StockCode>FBX-SMO30029-8</StockCode>
            <StockDescription>TARGET SOAP PDQ 2014 ASSEMBLED</StockDescription>
            <OrderQty>3.0</OrderQty>
            <OrderUom>EA</OrderUom>
            <PriceUom>EA</PriceUom>
            <AlwaysUsePriceEntered>Y</AlwaysUsePriceEntered>
            <UserDefined>2</UserDefined>
            <OrderLineID>OR-1810142</OrderLineID>
         </StockLine>
         <CommentLine>
            <Comment>Comment#1</Comment>
            <OrderLineID>OR-1810143</OrderLineID>
            <UserDefined>3</UserDefined>
            <LineActionType >A<LineActionType />
         </CommentLine>
         <CommentLine>
            <Comment>Comment#2</Comment>
            <OrderLineID>OR-1810144</OrderLineID>
            <UserDefined>4</UserDefined>
           <LineActionType >A<LineActionType />
         </CommentLine>
      </OrderDetails>
   </Orders>
</SalesOrders>

ANY help on it would be much appreciated ?


Solution

  • Firstly note that <LineActionType >A<LineActionType /> is not valid XML, so I am assuming you mean <LineActionType>A</LineActionType>.

    Anyway, if all CommentLine elements had a LineActionType and you just wanted to set them all to A, you could just add this template along with the identity template

    <xsl:template match="CommentLine/LineActionType">
       <xsl:copy>A</xsl:copy>
    </xsl:template>
    

    Alternatively, if LineActionType is not always present under a CommentLine, you could try adding these two templates instead. One to add it under any CommentLine, and another to prevent any existing one being output (so that it doesn't get output twice)

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