0
votes

using xslt 1.0 on python, I am trying to select a few items while specifying order:

<?xml version="1.0" encoding="UTF-8"?>
<items>
<item name='1'>
first
</item>
<item name='2'>
second
</item>
<item name='3'>
third
</item>
</items>

If I use a for-each with a big OR'd together list, I can get the items I want, but only in the original order of the xml source document above.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
  <html>
  <body>
        <xsl:for-each select="items/item[@name='2']|items/item[@name='1']">
<p>hi</p>
<xsl:value-of select="." />
</xsl:for-each>
  </body>
  </html>
    </xsl:template>
</xsl:stylesheet>

This produces:

hi
first
hi
second

But I would like to have it output:

hi
second
hi
first

I think using xsl:apply-templates might be the way to go, but I can't get it to work with even this simple example. What is the best way in xslt 1.0 to select elements in a specific order?

1
See the answer that har07 gave you (with the two apply-templates), the union operator | you use sorts its operands in document order so your attempt with select="items/item[@name='2']|items/item[@name='1']" does not define an order for the for-each, as you want to. In XSLT 2.0 you could use the comma operator ,, as in select="items/item[@name='2'],items/item[@name='1']", but XSLT 1.0 does not have that operator.Martin Honnen

1 Answers

2
votes

You can use <xsl:sort> to specify ordering especially when there is a specific logic to define the ordering, for example to order by name attribute value in descending order :

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">  
  <xsl:template match="/"> 
    <html> 
      <body> 
        <xsl:for-each select="items/item[@name='2' or @name='1']"> 
          <xsl:sort select="@name" data-type="number" order="descending"/>
          <p>hi</p>  
          <xsl:value-of select="."/> 
        </xsl:for-each> 
      </body> 
    </html> 
  </xsl:template> 
</xsl:stylesheet>

xsltransform demo 1

"I think using xsl:apply-templates might be the way to go, but I can't get it to work with even this simple example"

That's also possible, for example :

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">  
  <xsl:template match="/"> 
    <html> 
      <body> 
        <xsl:apply-templates select="items/item[@name='2']"/>
        <xsl:apply-templates select="items/item[@name='1']"/>
      </body> 
    </html> 
  </xsl:template> 

  <xsl:template match="items/item">
      <p>hi</p>  
      <xsl:value-of select="."/> 
  </xsl:template>
</xsl:stylesheet>

xsltransform demo 2

output :

<html>
   <body>
      <p>hi</p>
      second

      <p>hi</p>
      first

   </body>
</html>