From one of our systems an xml file is produced. I need to validate
this file before we send it to an external system for a very lenghty
process. I cannot change the xml file layout.
The solution i got today is very slow, and i need help to find another
solution.
Here is the xml file. It consists of a list of position ids (ESTOXX50
INDEX_BM_E and FTSE INDEX_BM_E), and below that a list of tags for each
position id. What i want to do is see that each entry not being in the
<groupCustomBuc ketList> list has an entry in each of the
<groupCustomBuc ket> tags below. And vice versa; that each position id
from each tag exists in the list of <equity>. See xsl transformation
below.
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="t.xsl"?>
<positions>
<equity>
<positionId>EST OXX50 INDEX_BM_E</positionId>
</equity>
<equity>
<positionId>FTS E INDEX_BM_E</positionId>
</equity>
<groupCustomBuc ketList>
<groupCustomBuc ket>
<customDimensio nName>Branch</customDimension Name>
<customBucketVa lue>BENCHMARK</customBucketVal ue>
<positionIdList >
<positionId>B MK ZENIT ESTOXX50 INDEX_BM_E</positionId>
<positionId>B MK ZENIT FTSE INDEX_BM_E</positionId>
</positionIdList>
</groupCustomBuck et>
<groupCustomBuc ket>
<customDimensio nName>Folder</customDimension Name>
<customBucketVa lue>BZ_ESTOX50</customBucketVal ue>
<positionIdList >
<positionId>B MK ZENIT ESTOXX50 INDEX_BM_E</positionId>
</positionIdList>
</groupCustomBuck et>
<groupCustomBuc ket>
<customDimensio nName>Folder</customDimension Name>
<customBucketVa lue>BZ_FTSE</customBucketVal ue>
<positionIdList >
<positionId>B MK ZENIT FTSE INDEX_BM_E</positionId>
</positionIdList>
</groupCustomBuck et>
<groupCustomBuc ket>
<customDimensio nName>Portfolio </customDimension Name>
<customBucketVa lue>BMK_ZENIT</customBucketVal ue>
<positionIdList >
<positionId>B MK ZENIT ESTOXX50 INDEX_BM_E</positionId>
<positionId>B MK ZENIT FTSE INDEX_BM_E</positionId>
</positionIdList>
</groupCustomBuck et>
<groupCustomBuc ket>
<customDimensio nName>CurrencyR egion</customDimension Name>
<customBucketVa lue>EUR</customBucketVal ue>
<positionIdList >
<positionId>B MK ZENIT ESTOXX50 INDEX_BM_E</positionId>
</positionIdList>
</groupCustomBuck et>
</groupCustomBuck etList>
</positions>
-----------------
Here is the xsl file. What i use is loads of call-template executes
which i guess is the performance issue. The code below works, but it's
really messy. And slow.
I have two "functions" loop_position and loop_tag that validates each
tag type against the position ids.
<?xml version="1.0"?>
<xsl:styleshe et version="1.0"
xmlns:xsl="http ://www.w3.org/1999/XSL/Transform">
<xsl:variable
name="tagstosca n">Branch,Portf olio,Folder,Cur rencyRegion,</xsl:variable>
<xsl:template match="/">
<xsl:element name="positions ">
<xsl:attribut e name="nbofcolum ns">
<xsl:call-template name="count_nb_ of_tags">
<xsl:with-param name="tags"><xs l:value-of select="$tagsto scan"
/></xsl:with-param>
<xsl:with-param name="count">0</xsl:with-param>
</xsl:call-template>
</xsl:attribute>
<!-- Find tags that are illegal -->
<xsl:call-template name="loop">
<xsl:with-param name="tags"><xs l:value-of select="$tagsto scan"
/></xsl:with-param>
</xsl:call-template>
</xsl:element>
</xsl:template>
<!-- Count the number of tags we are processing -->
<xsl:template name="count_nb_ of_tags">
<xsl:param name="tags" />
<xsl:param name="tag" select="substri ng-before($tags, ',')" />
<xsl:param name="count" />
<xsl:if test="string-length($tag) = 0"><xsl:valu e-of select="$count"
/> </xsl:if>
<xsl:if test="string-length($tags) > 0">
<xsl:call-template name="count_nb_ of_tags">
<xsl:with-param name="tags" select="substri ng-after($tags, ',')" />
<xsl:with-param name="count" select="$count + 1" />
</xsl:call-template>
</xsl:if>
</xsl:template>
<!-- Loop all tags we are processing, parsing the xml. Check two
directions: positions to tags, and reverse -->
<xsl:template name="loop">
<xsl:param name="tags" />
<xsl:param name="tag" select="substri ng-before($tags, ',')" />
<xsl:if test="string-length($tag) > 0">
<xsl:element name="position" >
<xsl:attribut e name="positionI d"></xsl:attribute>
<xsl:call-template name="loop_posi tion">
<xsl:with-param name="tags" select="$tag" />
</xsl:call-template>
<xsl:call-template name="loop_tag" >
<xsl:with-param name="tags" select="$tag" />
</xsl:call-template>
</xsl:element>
</xsl:if>
<xsl:if test="string-length($tags) > 0">
<xsl:call-template name="loop">
<xsl:with-param name="tags" select="substri ng-after($tags, ',')" />
</xsl:call-template>
</xsl:if>
</xsl:template>
<!-- Tag parsing -->
<xsl:template name="loop_tag" >
<xsl:param name="tags" />
<xsl:for-each select="positio ns/*/positionId">
<xsl:call-template name="find_id_i n_taglist">
<xsl:with-param name="id" select="." />
<xsl:with-param name="tag" select="$tags" />
</xsl:call-template>
</xsl:for-each>
</xsl:template>
<xsl:template name="find_id_i n_taglist">
<xsl:param name="id" />
<xsl:param name="tag" />
<xsl:if
test="string-length(/positions/groupCustomBuck etList/groupCustomBuck et/customDimension Name[.
= $tag]/../positionIdList/positionId[. = $id]) = 0">
<xsl:attribut e name="positionI d"><xsl:valu e-of select="$id"
/></xsl:attribute>
<xsl:variable name="fixedid"> <xsl:call-template
name="remove_sp ace"><xsl:with-param name="string" select="$tag"
/></xsl:call-template></xsl:variable>
<xsl:attribut e name="{$fixedid }">1</xsl:attribute>
</xsl:if>
</xsl:template>
<!-- Position parsing -->
<xsl:template name="loop_posi tion">
<xsl:param name="tags" />
<xsl:for-each
select="/positions/groupCustomBuck etList/groupCustomBuck et/customDimension Name[.
= $tags]/../positionIdList/positionId">
<xsl:call-template name="find_id_i n_positionlist" >
<xsl:with-param name="id" select="." />
<xsl:with-param name="tag" select="$tags" />
</xsl:call-template>
</xsl:for-each>
</xsl:template>
<xsl:template name="find_id_i n_positionlist" >
<xsl:param name="id" />
<xsl:param name="tag" />
<xsl:if test="string-length(/positions/*/positionId[. = $id]) = 0">
<xsl:attribut e name="positionI d"><xsl:valu e-of select="$id"
/></xsl:attribute>
<xsl:variable name="fixedid"> <xsl:call-template
name="remove_sp ace"><xsl:with-param name="string" select="$tag"
/></xsl:call-template></xsl:variable>
<xsl:attribut e name="{$fixedid }">1</xsl:attribute>
</xsl:if>
</xsl:template>
<!-- Remove spaces -->
<xsl:template name="remove_sp ace">
<xsl:param name="string" />
<xsl:choose>
<xsl:when test="contains( $string, ' ')">
<xsl:call-template name="remove_sp ace">
<xsl:with-param name="string">
<xsl:value-of select="substri ng-before($string, ' ')"
/><xsl:value-of select="substri ng-after($string, ' ')" />
</xsl:with-param>
</xsl:call-template>
</xsl:when>
<xsl:otherwis e>
<xsl:value-of select="$string " />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Override default template rules -->
<xsl:template match="*|/" mode="m">
<!-- Do nothing. Override default rule -->
</xsl:template>
<xsl:template match="processi ng-instruction()|c omment()" >
<!-- Do nothing. Override default rule -->
</xsl:template>
<xsl:template match="text() | @*">
<!-- Do nothing. Override default rule -->
</xsl:template>
</xsl:stylesheet>
Regards,
/Johan