0
votes

I want to create XSLT schema to transform my xml record. Here is an example of incoming xml

<Target>
   <name1>AMRXQUAL</name1>
   <name2>0</name2>
   <name3>217</name3>
   <name4>72</name4>
</Target>

This is expected output after xslt transformation :

<Target>
    <string_fields>
        <name1>AMRXQUAL</name1>
    </string_fields>
    <int_fields>
        <name2>0</name2>
        <name3>217</name3>
        <name4>72</name4>
    </int_fields>
</Target>

The idea is to check type of each element in Target and then move it to corresponding element on root level. If element type is integer we move it to int_fields, if element is string - we move it to string_fields and so on . Thank you in advance !

2
Does your processor support XSLT 2.0? --- P.S. Do not say "and so on". Enumerate every type you want to test for. - michael.hor257k
Yes, it supports XSLT 2.0. I need to check next types : boolean, string, integer an decimal. Thank you ! @michael.hor257k - Algrach
Which type has priority? Any integer is also a decimal, any number is also a string? - Martin Honnen
decimal has priority - Algrach

2 Answers

1
votes

With castable as you could check the type and then write a function returning your desired type prefix and use it in group-by:

 <xsl:function name="mf:get-type" as="xs:string">
      <xsl:param name="input"/>
      <xsl:sequence
        select="if ($input castable as xs:integer)
                then 'int'
                else if ($input castable as xs:decimal)
                then 'dec'
                else if ($input castable as xs:boolean)
                then 'boolean'
                else 'string'"/>
  </xsl:function>

  <xsl:template match="Target">
      <xsl:copy>
          <xsl:for-each-group select="*" group-by="mf:get-type(.)">
              <xsl:element name="{current-grouping-key()}_fields">
                  <xsl:copy-of select="current-group()"/>
              </xsl:element>
          </xsl:for-each-group>
      </xsl:copy>
  </xsl:template>
0
votes

Try this

    <xsl:template match="Target">
    <xsl:copy>
        <xsl:for-each-group select="*" group-adjacent="substring(local-name(), 1, 1)">
            <xsl:choose>
                <xsl:when test="current-grouping-key() = 's'">
                    <string_fields>
                        <xsl:apply-templates select="current-group()"/>
                    </string_fields>
                </xsl:when>
                <xsl:when test="current-grouping-key() = 'i'">
                    <int_fields>
                        <xsl:apply-templates select="current-group()"/>
                    </int_fields>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:apply-templates select="current-group()"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each-group>
    </xsl:copy>
</xsl:template>

See Transformation at https://xsltfiddle.liberty-development.net/6q1SDjN