Search

I have some problems with an XSLT that I can’t figure out (I have little XSLT experience), hopefully someone can help me out. I know it’s not Symphony-specific but this is the only forum I know that deals with XSL all the time.

How can you turn an XML from this:

<root>
  <item id="1" category="a"/>
  <item id="2" category="b"/>
  <item id="3" category="a"/>
  <item id="4" category="b"/>
  ...
</root>

To this:

<root>
  <category id="a">
    <item id="1"/>
    <item id="3"/>
    ...
  </category>
  <category id="b">
    <item id="2"/>
    <item id="4"/>
    ...
  </category>
  ...
</root>

I started with something like this:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="item">
  <category id="{@category}">
    <item id="{@id}"/>
  </category>
</xsl:template>

</xsl:stylesheet>

but this obviously creates one category element for each item (duplicating categories with the same id)

I then tried to get only the categories with a distinct-values:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
  <xsl:for-each select="distinct-values(root/item/@category)">
    <category id="{.}"/>
  </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

but this doesn’t seem to output anything (I’m testing against w3school’s “tryxslt” page with Opera 10.50 so I don’t know how reliable it is).

Thanks

Maybe this is helpful?

Muenchian Grouping is a life-saver. (But it’s hard to wrap your mind around it.)

Everyone inevitably comes to Meunchian grouping when using XSL (at some point). This is one of those things that makes you stand back and realise just how powerful XSL is as a templating language.

If you have any troubles Ixai, post back here - I’m sure one of us can give you some advice.

Thanks! I think I understand how it works now. And as an aside I got to learn the quirks of <xsl:sort/>. The link mentions two methods for finding out whether a record is the first with a certain key value (the first with generate-id() and the second with count()). Does anyone know if there’s any notable performance difference between them?

The XSL for the example in this post (just in case…):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:key name="categories" match="item" use="@category"/>

<xsl:template match="/">
  <root>
    <xsl:apply-templates/>
  </root>
</xsl:template>

<xsl:template match="root">
    <xsl:for-each select="item[count(. | key('categories', @category)[1]) = 1]">
      <!--<xsl:sort select="@category" data-type="number"/>-->
      <category id="{@category}">
        <xsl:for-each select="key('categories', @category)">
          <!--<xsl:sort select="@id" data-type="number"/>-->
          <item id="{@id}"/>
        </xsl:for-each>
      </category>
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

The performance will vary based upon the XSL interpreter - I don’t know what the figures are for the interpreter used by Symphony, but the generate-id method was always an order of magnitude faster under Xalan.

If you’re worried about performance at that level, try using the “Profile Devkit” extension to time the two different methods - I’d love to hear what you find.

Symphony uses GNOME’s libxml since PHP’s LibXML module is based on it. I’m not so worried about performance right now since my dataset is rather small right now, but if I ever get the chance to test something larger I’d gladly share it with you.

Create an account or sign in to comment.

Symphony • Open Source XSLT CMS

Server Requirements

  • PHP 5.3-5.6 or 7.0-7.3
  • PHP's LibXML module, with the XSLT extension enabled (--with-xsl)
  • MySQL 5.5 or above
  • An Apache or Litespeed webserver
  • Apache's mod_rewrite module or equivalent

Compatible Hosts

Sign in

Login details