Thomas Lann
Thomas Lann

Reputation: 1234

Counting the number of times an xslt transform is done

Do to political reasons, a customer wants me to implement a way to count the number of xslt transforms that are done on an xml document in a generic way instead of doing it another way. I realize variables can't be changed once they are initialized according to a few forums, but if I understand correctly, there is a work around using templates. Although, I'm having a hard time wrapping my head around it.

There would be 3 different types of counters: additions, modifications, and deletions. I would like to output the counts to some sort of file. I'm guessing a way to do this would be to use a second xslt based on the first. But I'm having time understanding how to do counts with xslt.

The original transform would look something like this

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"[
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>

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

<!--  <xsl:template match="is_gone|@value"/>  -->
<xsl:template match="is_gone"/>

<!-- Adding an element -->
<xsl:template match="viral_desc">
      <xsl:copy-of select="."/>
      <blarg_group>17</blarg_group>
</xsl:template>


<!-- modification -->
   <xsl:template match ="some_test_value/text()[.&lt; 500]">500 </xsl:template>
   <xsl:template match ="some_test_value/text()[.&gt; 2000]">2000 </xsl:template>

</xsl:stylesheet> 

Example XML data to transform

<class guid="a58bca48-cb0a-5f37-3a11-916e3a74959">
    <cork_id value="871222" valid="false"/>
    <merk_id value="11111" valid="false"/>
    <todd_id value="2188" valid="true"/>
    <name> Garp Toblabber </name>
    <classification>Sarcastic</classification>
    <is_gone>true</is_gone>
    <move>true
        <thingA>true</thingA>
        <thingB>true
            <subThingB>true </subThingB>
        </thingB>
    </move>
    <class_show_text> DA </class_show_text>
    <some_test_value> 3000 </some_test_value>
    <some_test_value> 3 </some_test_value>
    <some_test_value> 520 </some_test_value>
    <ew_tv_text> Drag </ew_tv_text>
    <standard_room_type> liquid </standard_room_type>    
    <viral_desc> Dull </viral_desc>
    <out_id euro_std="A" id="55" name="Nerf" environment="Volatile" category="Vague" modifier="Yes" is_out="false"/>
    <source/>
    <comments/>
</class>

Desired output would look something like the following

<r>
<add> 1 </add>
<del> 1 </del>
<mod> 2 </mod>
</r>

Upvotes: 0

Views: 202

Answers (1)

michael.hor257k
michael.hor257k

Reputation: 117140

The following stylesheet:

XSLT 1.0

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

<xsl:template match="/class">
    <r>
        <add><xsl:value-of select="count(viral_desc)"/></add>
        <del><xsl:value-of select="count(is_gone)"/></del>
        <mod><xsl:value-of select="count(some_test_value[. &lt; 500 or . > 2000])"/></mod>
    </r>
</xsl:template>

</xsl:stylesheet>

when applied to your input example, will return:

<?xml version="1.0" encoding="utf-8"?>
<r>
   <add>1</add>
   <del>1</del>
   <mod>2</mod>
</r>

To make it more generic and count the designated nodes at any level, use simply:

<xsl:template match="/">
    <r>
        <add><xsl:value-of select="count(//viral_desc)"/></add>
        <del><xsl:value-of select="count(//is_gone)"/></del>
        <mod><xsl:value-of select="count(//some_test_value[. &lt; 500 or . > 2000])"/></mod>
    </r>
</xsl:template>

Upvotes: 1

Related Questions