Lorenzo Castagno
Lorenzo Castagno

Reputation: 628

Modify XML Tag (Value of an Attribute) XSLT 1.0

Im trying to build an output file (based on a determined template) having as input another xml.

The xslt code (XSLT 1.0) used to build the output, is "divided" by sections.

I'm skipping the first part of the code... I was "assigning" the variables, for ex:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:date="http://exslt.org/dates-and-times" extension-element-prefixes="date">
    
<xsl:variable name="securityCode"select="/A/securityCode"/>
<!--and the others variables to I think is are not relevant for my question-->

The xslt (the original code has more sections than this, also I have to use it for different inputs to produce different outputs)

                                       <!--Here we call the templates-->

<xsl:template match="/">
 <Header>

 <xsl:call-template name="Header">
 <xsl:with-param name="securityCode" select = "$securityCode"/>
 <xsl:with-param name="generatedTime" select = "$generatedTime"/>
 </xsl:call-template>

 </Header>

</xsl:template>

                                       



<xsl:call-template name="StructureData">

<xsl:with-param name = "payDate"/>
<xsl:with-param name = "amount"/>
<xsl:with-param  name = "priRte"/> 
<xsl:with-param name = "settlement"/> 
<xsl:with-param name = "rate"/> 
<xsl:with-param name = "curr"/> 
<xsl:with-param name = "rdate"/>
<xsl:with-param name = "ID"/>
<xsl:with-param name = "CID" />
<xsl:with-param name = "Nom" />

</xsl:call-template>

                                     <!--Here we call "define" the templates-->
<xsl:template name = "Header" >
<xsl:param name = "securityCode" />
<xsl:param name = "generatedTime" />

 <NHeader>
  <MessageID><xsl:value-of select="$securityCode"/></MessageID>
 
  <Timezone>GMT</Timezone>
  <GeneratedTime><xsl:value-of select="$generatedTime"/></GeneratedTime>
  
 </NHeader>

</xsl:template>

<xsl:template name = "StructureData" >

<xsl:param name = "payDate"/>
<xsl:param name = "amount"/>
<xsl:param name = "priRte"/> 
<xsl:param name = "settlement"/> 
<xsl:param name = "rate"/> 
<xsl:param name = "curr"/> 
<xsl:param name = "rdate"/>
<xsl:param name = "ID"/>
<xsl:param name = "CID" />
<xsl:param name = "Nom" />
<xsl:param name = "securityCode" />
                    <Data2>
                      <ID><xsl:value-of select="$ID"/></ID>
                      <Sett><xsl:value-of select="$settlement"/></Sett>
                      <BuyOrSell value="Sell"/>
                      <price value="Price"><xsl:value-of select="$priRte"/></price>
                      <Cost><xsl:value-of select="$Nom"/></Cost>
                     <Accrual>
                        <Cashflow CFLType="Principal">
                          <Cid><xsl:value-of select="$CID"/></CID>
                          <CashflowPayment>
                            <PayDate><xsl:value-of select="$payDate"/></PayDate>
                            <Amount><xsl:value-of select="$amount"/></Amount>
                        </CashflowPayment>
                      </Cashflow>
                  </Accrual>
                </Data2>

</xsl:template>


</xsl:stylesheet>

Finally, my question:

I would like to modify (or rename it) the node value :

<BuyOrSell value="Sell"/>

Depending on the input condition (from an input) variable, let say secutityCode defined above.

Suppose (securityCode can be: 1 or 2)

  1. securityCode=1 then <BuyOrSell value="Sell"/>
  2. securityCode=2 then <BuyOrSell value="Buy"/>

I know how to modify nodes, but once I template as input...actually there are some hints: hint1 hint2 none of these works, or probably I don't how to implement it on my code.

Upvotes: 1

Views: 317

Answers (2)

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243579

Here is a compact way to do this in XSLT 1.0

(just in a single line like this: <BuyOrSell value="{$vOps[$psecurityCode]}"/> regardless of the number of different possible op-codes):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:param name="psecurityCode" select="1"/>
 <xsl:variable name="vTxs">
   <op>Sell</op>
   <op>Buy</op>
 </xsl:variable>
 
 <xsl:variable name="vOps" select="document('')/*/xsl:variable[@name='vTxs']/*"/>

  <xsl:template match="/">
    <BuyOrSell value="{$vOps[$psecurityCode]}"/>
  </xsl:template>
</xsl:stylesheet>

When this transformation is applied on any XML document (not used), the wanted, correct result is produced:

<BuyOrSell value="Sell"/>

If you replace the xsl:param declaration with: <xsl:param name="psecurityCode" select="2"/> then again the wanted result is produced:

<BuyOrSell value="Buy"/>

II. Explanation

  1. Using AVT (Attribute Value Templates)

  2. Using document('') to access the stylesheet document and its descendents

Upvotes: 2

Martin Honnen
Martin Honnen

Reputation: 167716

If you create an attribute with e.g.

<BuyOrSell>
  <xsl:attribute name="value">
    <xsl:choose>
      <xsl:when test="$securityCode = 1">Sell</xsl:when>
      <xsl:when test="$securityCode = 2">Buy</xsl:when>
    </xsl:choose>
  </xsl:attribute>
</BuyOrSell>

you can implement the condition, although in XSLT 1 that is a rather verbose way.

In general I would suggest to try to use template matching e.g.

<xsl:template match="/A/securityCode[. = 1]">
  <BuyOrSell>Sell</BuyOrSell>
</xsl:template>

<xsl:template match="/A/securityCode[. = 2]">
  <BuyOrSell>Buy</BuyOrSell>
</xsl:template>

and then further up in the tree processing use <xsl:apply-templates/> or <xsl:apply-templates select="securityCode"/> depending on your needs to implement the transformation.

Upvotes: 1

Related Questions