0
votes

I am trying to understand a piece of XSLT code for a work project, but I just can't figure out what calls what and how the values are passsed in correctly.

I have this code, which uses the apply-templates element to select the first element in the document type element:

<xsl:apply-templates select="DocumentType[string(text())][1]" mode="XmlString">
        <xsl:with-param name="name" select="'DocumentType'"/>
      </xsl:apply-templates>

A parameter is then passed into the template, which assign the correct value. The name attribute in the with-param matches the param element here:

<xsl:template match="*" mode="XmlString">
    <xsl:param name="name"/>
    <!-- Check the "name" parameter : madantory / optional -->
    <xsl:call-template name="MandatoryOrOptional">
      <xsl:with-param name="name" select="$name"/>
      <xsl:with-param name="value" select="."/>
    </xsl:call-template>
  </xsl:template>

But I'm not sure why and how the value gets passed. This is used repeatedly throughout the map whenever a value needs to be mapped.

Normally I would just create the tags needed and use the xsl:value-of element to get my desired value from the source document. If anyone could enlighten me as to how this code works in practice I would be grateful. The few times I've used apply-templates, I had already defined a template in my XSLT and then used the match attribute to apply it.

1
This isn't something the Designer would do. Is it a pattern you really need to replicate? Maybe the original developer was trying to be too clever for anyone else to follow. :(Johns-305
What do you mean by the first statement? Yes, I would like to replicate this pattern if possible as it is used extensively.Leth
I mean it's not something the BizTalk Mapper would do.Johns-305

1 Answers

0
votes

This method (i.e., passing something across multiple templates) is useful if we consider that apply-template is analogous to the for-each. In this comparison, the with-param is analogous to the variable.

If you need to pass a variable through multiple templates you can do this in the method you are seeing. Because the value assigned to the param "name" in XMLString is out of scope when you enter MandatoryOrOptional you need a way to indicate what "name" is when you enter the MandatoryOrOptional template. The way to do this is to pass "name" as a parameter. Effectively expanding the scope of the variable into the new template.

I've added comments to your code snippet to try to detail this "in code."

<xsl:template match="*" mode="XmlString">
    <xsl:param name="name"/> 
        <!--This brings the name from the first template and stores it -->
        <!--This is treated as a variable with a scope of the template -->
    <xsl:call-template name="MandatoryOrOptional">
      <xsl:with-param name="name" select="$name"/>
         <!-- This effectively expands the scope of the variable $name -->
         <!-- The name sent from the first template is now in scope for MandatoryOrOptional -->
      <xsl:with-param name="value" select="."/>
    </xsl:call-template>
</xsl:template>

It is debatable on if it is a good practice to keep the name="name" for each parameter, but I think it makes sense and have used it several times. It makes it easier to follow the "variable" through the code.