30

can array's be created and used in xslt? If so are there suitable examples online to study? If not is there a way to store values in a way that mimics an array?

1
  • Good question (+1). See my answer for a detailed decription of the closest to array XPath (and XSLT) data type. Commented Jul 21, 2010 at 16:16

5 Answers 5

28

With XSLT 2.0 you can model any data type you want to.

As example:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" omit-xml-declaration="yes"/>
    <xsl:variable name="array" as="element()*">
        <Item>A</Item>
        <Item>B</Item>
        <Item>C</Item>
    </xsl:variable>
    <xsl:template match="/">
        <xsl:value-of select="$array[2]"/>
    </xsl:template>
</xsl:stylesheet>

With any input, output:

B

In XSLT 1.0 there is not Temporaly Result Tree data type. There is a Result Tree Fragment data type that does not allow node-set operator. So, the only way to go is with extensions functions: in this case node-set() from EXSLT (MSXSL has a built-in node-set() extension, also).

So, in XSLT 1.0 without extensions you can have only inline data model, or by params or by external document. As example:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" omit-xml-declaration="yes"/>
    <xsl:variable name="inline-array">
        <Item>A</Item>
        <Item>B</Item>
        <Item>C</Item>
    </xsl:variable>
    <xsl:param name="array" select="document('')/*/xsl:variable[@name='inline-array']/*"/>
    <xsl:template match="/">
        <xsl:value-of select="$array[2]"/>
    </xsl:template>
</xsl:stylesheet>

Result, with any input:

B

Only if you want to, I can provide you a XSLT 1.0 plus extensions example (It's not standar...)

Sign up to request clarification or add additional context in comments.

5 Comments

@Alejandro - from what I can see, you are simply using the name array which is a collection of element nodes.
@Oded: That's right! That's the concept of data modeling. The principal feature of array data types is random access. This model cover that as show.
@Alejandro - naming something an array doesn't make it an array. The closest thing to one in xsl is a node-set.
@Oded: Node sets are not the "closest thing" to array, because they are sets (not repeated nodes). My model (an all-school TAD) allow repeated content. Also, I've forgotten XPath 2.0 "secuence" data type.
XSLT 1.0 solution does not work.
11

The XPath 2.0 sequence (available in XSLT 2+) is the closest thing to an array:

(1 to 10)[3]

evaluates to 3

('a', 'b', 'a', 'c')[3]

evaluates to 'a'

The items of a sequence can be of any conceivable type allowed in XPath, with the exception of sequence itself -- nested sequences are not allowed.

Do note: Sequences are not the same as arrays:

  1. Sequences are immutable. Any updating operation on a sequence (appending or prepending an item, inserting an item or removing an item) produces a new sequence.

  2. The access time to the n-th item is not guaranteed to be O(1) as this is for arrays, and may be O(n).

3 Comments

+1 good answer! I've realized later that I forgotten sequence data type. I missed defending the idea of data modeling.
@Alejandro: What is "data modelling" ? :)
Sorry for my in english. I should say Abstract Data Type.
5

No, not as such. The closest concept is node-sets, which are collections of nodes. Whenever the result of a select is a number of nodes, you get a node-set. These can be accessed with a index notation (starting with 1), so the first element of the node-set can be accessed with notation such as selectedNodes[1].

Comments

2

If need filter and foreach. (csv example)

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" version="2.0">
   <xsl:output method="text" omit-xml-declaration="yes" />
   <xsl:variable name="array" as="element()*">
      <column name="Company" enable="true">Company</column>
      <column name="User" enable="true">User</column>
   </xsl:variable>
   <xsl:variable name="separator">
      <xsl:text>;</xsl:text>
   </xsl:variable>
   <xsl:variable name="newline">
      <xsl:text>&#xa;</xsl:text>
   </xsl:variable>
   <!-- Output the CSV header -->
   <xsl:for-each select="msxsl:node-set($array)/column[@enable = 'true']">
      <xsl:value-of select="." />
      <xsl:if test="position() != last()">
         <xsl:value-of select="$separator" />
      </xsl:if>
   </xsl:for-each>
   <xsl:value-of select="$newline" />

<!-- your code inserted row -->

</xsl:stylesheet>

Read more

Comments

1

With XSLT 2.0 you can simply use

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">
    <xsl:output omit-xml-declaration="yes"/>
    <xsl:template match="/">
      <xsl:variable name="array" select="('A','B','C')"/> 
      <xsl:value-of select="$array[2]"/>
    </xsl:template>
</xsl:stylesheet>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.