creating arrays in xslt
Asked Answered
P

5

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?

Pisarik answered 21/7, 2010 at 13:50 Comment(1)
Good question (+1). See my answer for a detailed decription of the closest to array XPath (and XSLT) data type.Liliuokalani
K
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...)

Kempis answered 21/7, 2010 at 14:7 Comment(5)
@Alejandro - from what I can see, you are simply using the name array which is a collection of element nodes.Pokpoke
@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.Kempis
@Alejandro - naming something an array doesn't make it an array. The closest thing to one in xsl is a node-set.Pokpoke
@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.Kempis
XSLT 1.0 solution does not work.Michalmichalak
L
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).

Liliuokalani answered 21/7, 2010 at 16:15 Comment(3)
+1 good answer! I've realized later that I forgotten sequence data type. I missed defending the idea of data modeling.Kempis
@Alejandro: What is "data modelling" ? :)Liliuokalani
Sorry for my in english. I should say Abstract Data Type.Kempis
P
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].

Pokpoke answered 21/7, 2010 at 13:53 Comment(0)
O
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

Originally answered 5/3, 2019 at 13:38 Comment(0)
D
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>
Dextrogyrate answered 11/8, 2018 at 15:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.