Tom Arm
Tom Arm

Reputation: 143

Tokenize | Transform text from XSL to XML

XSLT: 1.0

I use XSLT 1.0. Below I paste Original output date:

<attributes>
<![CDATA[Wodoodporność: 3 ATM - Średnica: 62 mm - Rodzaj: Męskie - Materiał: Stal nierdzewna - Materiał paska: Skóra - Mechanizm: Kwarcowy - Funkcje: Wielofunkcyjność - Szkiełko: Mineralne - Rodzaj produktu: Zegarek na rękę - Opakowanie: Oficjalne pudełko]]></attributes>

Now for test I little change tags in output date: (because our xslt template currently working only with <input fields:

<input fields="Wodoodporność: 3 ATM - Średnica: 62 mm - Rodzaj: Męskie - Materiał: Stal nierdzewna - Materiał paska: Skóra - Mechanizm: Kwarcowy - Funkcje: Wielofunkcyjność - Szkiełko: Mineralne - Rodzaj produktu: Zegarek na rękę - Opakowanie: Oficjalne pudełko"/>

BELOW XSLT 1.0 CODE:

<xsl:stylesheet 
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:ext="http://exslt.org/common"
    exclude-result-prefixes="ext">

<!-- Tokenize a string that's pipe separated -->
<xsl:template name="tokenize">
    <xsl:param name="text"/>
    <xsl:param name="separator" select="'-'"/>
    
    <xsl:choose>
        <xsl:when test="not(contains($text, $separator))">
            <item>
                <xsl:value-of select="normalize-space($text)"/>
            </item>
        </xsl:when>
        <xsl:otherwise>
            <item>
                <xsl:value-of select="normalize-space(substring-before($text, $separator))"/>
            </item>
            <xsl:call-template name="tokenize">
                <xsl:with-param name="text" select="substring-after($text, $separator)"/>
            </xsl:call-template>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

<xsl:template match="/input">
    <!-- Tokenize the 'fields' attribute on /input -->
    <xsl:variable name="name-set">
        <xsl:call-template name="tokenize">
            <xsl:with-param name="text">
                <xsl:value-of select="@fields"/>
            </xsl:with-param>
        </xsl:call-template>
    </xsl:variable>

    <!-- Tokenize the 'values' attribute on /input -->
    <xsl:variable name="value-set">
        <xsl:call-template name="tokenize">
            <xsl:with-param name="text">
                <xsl:value-of select="@values"/>
            </xsl:with-param>
        </xsl:call-template>
    </xsl:variable>

    <!-- Generate our output -->
    <Output>
            <attributename1><xsl:copy-of select="ext:node-set($name-set)/item[1]/text()"/></attributename1>
            <attributevalue1><xsl:copy-of select="ext:node-set($value-set)/item[1]/text()"/></attributevalue1>
                        <attributename2><xsl:copy-of select="ext:node-set($name-set)/item[2]/text()"/></attributename2>
            <attributevalue2><xsl:copy-of select="ext:node-set($value-set)/item[2]/text()"/></attributevalue2>
                        <attributename3><xsl:copy-of select="ext:node-set($name-set)/item[3]/text()"/></attributename3>
            <attributevalue3><xsl:copy-of select="ext:node-set($value-set)/item[3]/text()"/></attributevalue3>
                        <attributename4><xsl:copy-of select="ext:node-set($name-set)/item[4]/text()"/></attributename4>
            <attributevalue4><xsl:copy-of select="ext:node-set($value-set)/item[4]/text()"/></attributevalue4>
                        <attributename5><xsl:copy-of select="ext:node-set($name-set)/item[5]/text()"/></attributename5>
            <attributevalue5><xsl:copy-of select="ext:node-set($value-set)/item[5]/text()"/></attributevalue5>
                        <attributename6><xsl:copy-of select="ext:node-set($name-set)/item[6]/text()"/></attributename6>
            <attributevalue6><xsl:copy-of select="ext:node-set($value-set)/item[6]/text()"/></attributevalue6>
                        <attributename7><xsl:copy-of select="ext:node-set($name-set)/item[7]/text()"/></attributename7>
            <attributevalue7><xsl:copy-of select="ext:node-set($value-set)/item[7]/text()"/></attributevalue7>
                        <attributename8><xsl:copy-of select="ext:node-set($name-set)/item[8]/text()"/></attributename8>
            <attributevalue8><xsl:copy-of select="ext:node-set($value-set)/item[8]/text()"/></attributevalue8>
                        <attributename9><xsl:copy-of select="ext:node-set($name-set)/item[9]/text()"/></attributename9>
            <attributevalue9><xsl:copy-of select="ext:node-set($value-set)/item[9]/text()"/></attributevalue9>
                        <attributename10><xsl:copy-of select="ext:node-set($name-set)/item[10]/text()"/></attributename10>
            <attributevalue10><xsl:copy-of select="ext:node-set($value-set)/item[10]/text()"/></attributevalue10>
            </Output>
</xsl:template>
</xsl:stylesheet>

Currently I get Result:

<?xml version="1.0" encoding="UTF-8"?><Output><attributename1>Wodoodporność: 3 ATM</attributename1><attributevalue1/><attributename2>Średnica: 62 mm</attributename2><attributevalue2/><attributename3>Rodzaj: Męskie</attributename3><attributevalue3/><attributename4>Materiał: Stal nierdzewna</attributename4><attributevalue4/><attributename5>Materiał paska: Skóra</attributename5><attributevalue5/><attributename6>Mechanizm: Kwarcowy</attributename6><attributevalue6/><attributename7>Funkcje: Wielofunkcyjność</attributename7><attributevalue7/><attributename8>Szkiełko: Mineralne</attributename8><attributevalue8/><attributename9>Rodzaj produktu: Zegarek na rękę</attributename9><attributevalue9/><attributename10>Opakowanie: Oficjalne pudełko</attributename10><attributevalue10/></Output>

I almost managed to achieve the effect. Can anyone give me a hint to get the below result?

What I try to do:

enter image description here

Upvotes: 0

Views: 48

Answers (1)

michael.hor257k
michael.hor257k

Reputation: 116959

See if this example can get you further:

XML

<attributes>
<![CDATA[Wodoodporność: 3 ATM - Średnica: 62 mm - Rodzaj: Męskie - Materiał: Stal nierdzewna - Materiał paska: Skóra - Mechanizm: Kwarcowy - Funkcje: Wielofunkcyjność - Szkiełko: Mineralne - Rodzaj produktu: Zegarek na rękę - Opakowanie: Oficjalne pudełko]]></attributes>

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="/">
    <output>
        <xsl:call-template name="tokenize">
            <xsl:with-param name="text" select="normalize-space(attributes)"/>
        </xsl:call-template>
    </output>
</xsl:template>

<xsl:template name="tokenize">
    <xsl:param name="text"/>
    <xsl:param name="delimiter" select="' - '"/>
        <xsl:variable name="token" select="substring-before(concat($text, $delimiter), $delimiter)" />
        <xsl:if test="$token">
            <xsl:element name="{translate(substring-before($token, ': '), ' ', '_')}">
                <xsl:value-of select="substring-after($token, ': ')" />
            </xsl:element>
        </xsl:if>
        <xsl:if test="contains($text, $delimiter)">
            <!-- recursive call -->
            <xsl:call-template name="tokenize">
                <xsl:with-param name="text" select="substring-after($text, $delimiter)"/>
            </xsl:call-template>
        </xsl:if>
</xsl:template>

</xsl:stylesheet>

Result

<?xml version="1.0" encoding="UTF-8"?>
<output>
  <Wodoodporność>3 ATM</Wodoodporność>
  <Średnica>62 mm</Średnica>
  <Rodzaj>Męskie</Rodzaj>
  <Materiał>Stal nierdzewna</Materiał>
  <Materiał_paska>Skóra</Materiał_paska>
  <Mechanizm>Kwarcowy</Mechanizm>
  <Funkcje>Wielofunkcyjność</Funkcje>
  <Szkiełko>Mineralne</Szkiełko>
  <Rodzaj_produktu>Zegarek na rękę</Rodzaj_produktu>
  <Opakowanie>Oficjalne pudełko</Opakowanie>
</output>

Note that this will fail if any of the prefixes contains other characters besides space that makes it an invalid event name.

Upvotes: 2

Related Questions