Tom Arm
Tom Arm

Reputation: 143

Issue with transform XSLT to XML

XSLT 1.0

Here is input XML:

<?xml version="1.0" encoding="UTF-8"?>
<products>
    <product>
        <id_brand>45</id_brand>
        <brand_name><![CDATA[DIESEL]]></brand_name>
        <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>
    </product>
</products>

From this XML I need get only content from tag attributes. Im 100% sure everything is OK with create tags from this description. Only is issues with tags <products> and <product> in XSLT template.

I use below XSLT template:

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

But something went wrong.

I try from above code to get result:

<?xml version="1.0" encoding="UTF-8"?>
<products>
<product>
  <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>
</product>
</products>

update: @michael.hor257k you have right. But see what happens. When <products><product>...</product><product>...</product> </products> occurs twice or more.

Everytime I get only result:

<product>
   <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>
</product>

This above result is from input: enter image description here

Upvotes: 0

Views: 44

Answers (1)

michael.hor257k
michael.hor257k

Reputation: 117175

But something went wrong.

That "something" is context. You are in the context of products - but attributes is a child of product - therefore your instruction:

<xsl:with-param name="text" select="normalize-space(attributes)"/>

selects nothing. Change it to:

<xsl:with-param name="text" select="normalize-space(product/attributes)"/>

--- added ---

If you have multiple product elements, then you probably want to do:

<xsl:template match="/products">
    <products>
        <xsl:for-each select="product">
            <product>
                <xsl:call-template name="tokenize">
                    <xsl:with-param name="text" select="normalize-space(attributes)"/>
                </xsl:call-template>
            </product>
        </xsl:for-each>
    </products>
</xsl:template>

It's hard to be sure without an example showing a representative input (as code) and the expected output.

Upvotes: 1

Related Questions