Souvik04
Souvik04

Reputation: 21

How to apply templates dynamically by using name()?

I am transforming XSLT to JSON from a source XML. I want the array type elements to be converted into "elements : []"

From the given xslt I am matching the node name and applying the template. But how to do that dynamically for every array type element or I can choose which element needs to be converted to array Type element in JSON.

Here is my source XML

<order>
  <email>[email protected]</email>
<tax-lines>
    <tax-line>
      <title>CGST</title>
      <price>29.00</price>
      <rate>0.2</rate>
    </tax-line>  
  </tax-lines>

  <freight-Lines>
    <freight-Line>
      <title>CGST</title>
      <price>29.00</price>
      <rate>0.2</rate>
    </freight-Line>
  </freight-Lines>
</order>

XSLT:

  <xsl:when test="name()= 'tax-lines'">
         [<xsl:apply-templates select="*" mode="ArrayElement"/>] 
      </xsl:when>

Using this I am having the Output Json as:

    {

    "order" :
        {

    "email" :"[email protected]",
    "tax-lines" :
         [
        {

    "title" :"CGST",
    "price" :"29.00",
    "rate" :"0.2"
        }
      ] 

        }
      }

Is there anyway by which I can do the same on 'freight-Lines' array dynamically?Means I want to do this line dynamically

<xsl:when test="name()= 'tax-lines'">
         [<xsl:apply-templates select="*" mode="ArrayElement"/>] 
      </xsl:when>

Upvotes: 2

Views: 172

Answers (1)

Michael Kay
Michael Kay

Reputation: 163262

One way of approaching this would be to control the transformation using some kind of mapping schema. So you might have:

From this you might generate a stylesheet containing set of template rules, for example:

<xsl:template match="tax-lines | freight-lines">
  <xsl:text>[</xsl:text>
  <xsl:for-each select="*">
    <xsl:if test="position() != 1">,</xsl:if>
    <xsl:apply-templates select="."/>
  <xsl:text>]</xsl:text>
</xsl:template>

<xsl:template match="tax-line | freight-line">
  <xsl:text>{</xsl:text>
  <xsl:for-each select="*">
    <xsl:if test="position() != 1">,</xsl:if>
    <xsl:text>"</xsl:text>
    <xsl:value-of select="local-name()"/>
    <xsl:text>":</xsl:text>
    <xsl:apply-templates select="."/>
  <xsl:text>}</xsl:text>
</xsl:template>

<xsl:template match="*[. castable as xs:double]">
  <xsl:value-of select="."/>
</xsl:template>

<xsl:template match="*">
  <xsl:text>"</xsl:text>
  <xsl:value-of select="."/>
  <xsl:text>"</xsl:text>
</xsl:template>

So you basically have a set of patterns that are used to map different XML elements to JSON, with a skeleton template rule for each one; your mapping schema defines which pattern to use for each element in your source document (with a default), and you then convert the mapping schema to a stylesheet that associates each element name with the corresponding template rule.

Upvotes: 2

Related Questions