📜 ⬆️ ⬇️

Tree in the drop down list using XSLT

Suppose we have something hierarchical on our site. For example, product categories. Categories have subcategories and so on. And let us want to bring this hierarchy to the drop-down list.

For example, our structure is expressed in the following XML:
< categories >
< category id ="1" title ="" >
< categories >
< category id ="2" title ="Intel" >
< categories >
< category id ="3" title ="Intel Core LGA775" >
< categories />
</ category >
< category id ="4" title ="Intel Core i7 LGA1366" >
< categories />
</ category >
</ categories >
</ category >
< category id ="6" title ="AMD" >
< categories >
< category id ="6" title ="AMD Athlon AM2" >
< categories />
</ category >
< category id ="7" title ="AMD Athlon II AM3" >
< categories />
</ category >
</ categories >
</ category >
</ categories >
</ category >
< category id ="8" title =" " >
< categories >
< category id ="9" title ="SATA" >
< categories >
< category id ="10" title ="Seagate" >
< categories />
</ category >
< category id ="11" title ="Western Digital" >
< categories />
</ category >
</ categories >
</ category >
< category id ="12" title ="IDE" >
< categories >
< category id ="13" title ="Seagate" >
< categories />
</ category >
< category id ="14" title ="Western Digital" >
< categories />
</ category >
</ categories >
</ category >
</ categories >
</ category >
</ categories >


* This source code was highlighted with Source Code Highlighter .
NB: In fact, storing strings in attributes is not good, they should be made as separate nodes and wrapped in CDATA. However, here the title is an attribute in order to save space. So please do not take a bad example.
So, we have to create a drop-down list from this XML. The easiest way to do this is to write the following conversion:
< xsl:stylesheet version ="1.0" xmlns:xsl ="http://www.w3.org/1999/XSL/Transform" >
< xsl:output method ="html" indent ="yes" />

< xsl:template match ="categories" >
< select >
< option value ="0" > </ option >
< xsl:apply-templates select ="//category" />
</ select >
</ xsl:template >

< xsl:template match ="category" >
< option value ="{@id}" >
< xsl:value-of select ="@title" />
</ option >
</ xsl:template >
</ xsl:stylesheet >

* This source code was highlighted with Source Code Highlighter .

As a result, we get this picture
Ugly list
In general, it works, but I want the category tree to look like a tree. And, since we have select here, we can only get this tree by placing spaces in the right places. There are, of course, optgroup , but in this case they will not save us, because categories can have arbitrarily large nesting.

Decision


Such a bike solves the given task:
  < xsl: stylesheet version = "1.0" xmlns: xsl = "http://www.w3.org/1999/XSL/Transform" > 
< xsl: output method = "html" indent = "yes" />

< xsl: template match = "/" >
< select >
< option value = "0" > Root Category </ option >
< xsl: call-template name = "cat_tree" >
< xsl: with-param name = "space" select = "'& # 160; & # 160;'"
/>
</ xsl: call-template >
</ select >
</ xsl: template >

< xsl: template name = "cat_tree" match = "categories" >
< xsl: param name = "space" />
< xsl: for-each select = "categories / category" >
< option value = "{@ id}" >
< xsl: value-of select = "$ space" />
< xsl: value-of select = "@ title" />
</ option >
< xsl: if test = "./ categories" >
< xsl: call-template name = "cat_tree" >
< xsl: with-param name = "space" select = "concat ($ space,
  '& # 160; & # 160;' 
) " />
</ xsl: call-template >
</ xsl: if >
</ xsl: for-each >
</ xsl: template >
</ xsl: stylesheet >

* This source code was highlighted with Source Code Highlighter .

As a result, we obtain the following:
Beautiful tree

')

Source: https://habr.com/ru/post/65077/


All Articles