Re: [xsl] fill an array in javascript

Subject: Re: [xsl] fill an array in javascript
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Fri, 23 Nov 2001 12:14:29 +0000
Hi Nathalie,

> I have to create an array and fill it with some text chosen out of a
> xml-file. A javascript-function() calls a named template that should
> get the wanted text()-Elements out of the .xml. But I have problems
> with variables and their concat-function, and I'm not sure if the
> whole template will work.

It's always confusing generating JavaScript using XSLT :) I'm a bit
confused about what you're doing, though, because you seem to be
generating an N-item array of 2-item arrays. I think that given the
XML:

<?xml version="1.0" encoding="UTF-8"?>
<modul>
  <phonetique>
    <lecon id="10">
      <texte_initial id="11">
        <titre>Title</titre>
        <texte>FirstText</texte>
        <texte>SecondText</texte>
        <texte>ThirdText</texte>
      </texte_initial>
    </lecon>
  </phonetique>
</modul>

you want to generate an array that looks like:

  [['Title', 'FirstText'],
   ['Title', 'SecondText'],
   ['Title', 'ThirdText']]

It also looks as though you might be trying to group the various texte
elements by their preceding titre elements, such that the first item
in each sub-array is the value of the nearest preceding titre element.

I think that the easiest way to create this array in JavaScript is
with:

  var XT_HTML = new Array(
                  new Array('Title', 'FirstText'),
                  new Array('Title', 'SecondText'),
                  new Array('Title', 'ThirdText')
                    );

(I added spaces just to make the pattern clear - they probably
shouldn't be there in the actual JavaScript.)

The static information here is the first and last line:

  <xsl:text>var XT_HTML = new Array(</xsl:text>
  ...
  <xsl:text>);</xsl:text>

In between, you need to iterate over each of the texte elements. For
each one you need to create the text "new Array('", followed by the
name of its closest preceding titre sibling, followed by the text "',
'", followed by the value of the texte element you're looking at,
followed by the text "')". For all but the last one, you also need to
add a comma at the end.

You can iterate over the texte elements with xsl:for-each, as follows:

  <xsl:text>var XT_HTML = new Array(</xsl:text>

  <xsl:for-each select="/modul/phonetique/lecon/texte_initial/texte">
    <xsl:text>new Array('</xsl:text>
    <xsl:value-of select="preceding-sibling::titre[1]" />
    <xsl:text>', '</xsl:text>
    <xsl:value-of select="." />
    <xsl:text>')</xsl:text>
    <xsl:if test="position() != last()">, </xsl:if>
  </xsl:for-each>

  <xsl:text>);</xsl:text>

If you prefer, you can combine the xsl:text and xsl:value-of elements
in the xsl:for-each into a single xsl:value-of with a concat()
function, as follows:

  <xsl:text>var XT_HTML = new Array(</xsl:text>

  <xsl:for-each select="/modul/phonetique/lecon/texte_initial/texte">
    <xsl:value-of select='concat("new Array(&apos;",
                                 preceding-sibling::titre[1],
                                 "&apos;, &apos;", ., "&apos;)")' />
    <xsl:if test="position() != last()">, </xsl:if>
  </xsl:for-each>

  <xsl:text>);</xsl:text>

Personally I find this more confusing because of the fact that you
have to escape the apostrophes.

Note in the above that you hardly ever have to go down to the text
node children of an element - usually getting the string value of the
element gets you what you need, and leads to more readable code.

If you'd prefer to generate the array another way, or if I've assumed
wrong about what array you're trying to generate, then please post
again with more details.

I hope that helps,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread