Hi Folks,
I am looking for a solution as to how I can mask some data that is part of a CDATA element.
My currently implemented xslt-1 script works fine when my xml element/attribute is not placed inside cdata, for example, in the following xml snippet, I masked <CreditCardNumber> element's data:
Input XML:
<?xml version="1.0" encoding="UTF-8"?>
<fareRequest da="true">
<vcrs>
<vcr>U2</vcr>
</vcrs>
<fareTypes/>
<tourOps/>
<flights>
<flight depApt="SXF" depDate="2012-04-19" dstApt="BUD"/>
<flight depApt="BUD" depDate="2012-04-25" dstApt="SXF"/>
</flights>
<CreditCardNumber>123456123</CreditCardNumber>
<limit>20</limit>
<offset>0</offset>
<waitOnList>
<waitOn>ALL</waitOn>
</waitOnList>
<coses/>
</fareRequest>
XSLT-1 Script:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.2" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ota="http://www.opentravel.org/OTA/2003/05" xmlns:anyway="http://anyway.com/webservices/" xmlns:k="http://webservices.kuoni.ch" xmlns:xft="http://www.exchangefortravel.org/xft/current" xmlns:tu="http://tempuri.org/" xmlns:jet2="http://Jet2.Com/External/2009/01/V4">
<xsl:output encoding="UTF-8" version="1.0" method="xml" indent="yes" cdata-section-elements="anyway:request k:request k:ForwardRequestResult xft:NameText xft:Description xft:URL xft:From xft:To xft:Code tu:XRq tu:ProcessTransactionXFTUResult libelle nom prenom adresse1 ville pays email"/>
<xsl:strip-space elements="*"/>
<!--add coma separated element names without namespace prefix to be masked, dont remove first coma! -->
<xsl:param name="names">!,Number,CCV,cc_number,cc_cvv,AccountNumber,CardSecurityCode,card_number,options,CreditCardNumber,CardNumber,IssueNumber,SecurityCode,</xsl:param>
<xsl:template match="/">
<xsl:apply-templates select="node()"/>
</xsl:template>
<xsl:template match="@*">
<xsl:variable name="attr-name" select="concat(',' , local-name() , ',')"/>
<xsl:attribute name="{name()}" namespace="{namespace-uri()}">
<xsl:choose>
<xsl:when test="string-length(substring-before($names, $attr-name)) > 0">
<xsl:call-template name="mask"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</xsl:template>
<xsl:template match="text()">
<xsl:copy/>
</xsl:template>
<xsl:template match="*">
<xsl:variable name="el-name" select="concat(',' , local-name(), ',')"/>
<xsl:choose>
<xsl:when test="string-length(substring-before($names, $el-name)) > 0">
<xsl:element name="{name()}" namespace="{namespace-uri()}">
<xsl:call-template name="mask"/>
</xsl:element>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="*"/>
</xsl:when>
<xsl:otherwise>
<xsl:element name="{name()}" namespace="{namespace-uri()}">
<xsl:apply-templates select="@*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="index-of">
<xsl:param name="param1"/>
<xsl:param name="param2"/>
<xsl:value-of select="string-length(substring-before(concat(' ' ,$param1), $param2))"/>
</xsl:template>
<xsl:template name="mask">
<xsl:variable name="length" select="string-length(.)"/>
<xsl:choose>
<xsl:when test="$length > 3">
<xsl:value-of select="concat ('************', substring(.,$length - 1, 2))"/>
</xsl:when>
<xsl:when test="$length > 1">***</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Output XML:
<?xml version="1.0" encoding="UTF-8"?>
<fareRequest da="true">
<vcrs>
<vcr>U2</vcr>
</vcrs>
<fareTypes/>
<tourOps/>
<flights>
<flight depApt="SXF" depDate="2012-04-19" dstApt="BUD"/>
<flight depApt="BUD" depDate="2012-04-25" dstApt="SXF"/>
</flights>
<CreditCardNumber>************23</CreditCardNumber>
<limit>20</limit>
<offset>0</offset>
<waitOnList>
<waitOn>ALL</waitOn>
</waitOnList>
<coses/>
</fareRequest>
In the above example <CreditCardNumber>************23</CreditCardNumber> is masked properly.
But when in my XML, I have the following scenario:
<?xml version="1.0" encoding="UTF-8"?>
<fareRequest da="true">
<vcrs>
<vcr>U2</vcr>
</vcrs>
<fareTypes/>
<tourOps/>
<flights>
<flight depApt="SXF" depDate="2012-04-19" dstApt="BUD"/>
<flight depApt="BUD" depDate="2012-04-25" dstApt="SXF"/>
</flights>
<![CDATA[<CreditCardNumber>123456123</CreditCardNumber>]]>
<limit>20</limit>
<offset>0</offset>
<waitOnList>
<waitOn>ALL</waitOn>
</waitOnList>
<coses/>
</fareRequest>
That is <CreditCardNumber> inside CDATA, the script does not mask the data. Or in other words, everything that is contained inside CDATA, is ignored because it is not considered as an element or attribute by the xslt processor.
Could somebody help me out in fixing this problem?
Please note that my script is in XSLT 1.
Thanks.