问题
I'm just figuring out how XSL works... mostly. I have 3 nodes (STUX, KbnApp, KbnStorge) that I want to transform in the same way except for how their list of "Servers" children are sorted. I wanted to do this with a single template that uses an xsl:if to choose an alternate sorting method for the "STUX". But I couldn't get it to work. The STUX Servers should end up in descending order, the others should stay in whatever order they are currently in.
Here is my XML
<?xml version="1.0" encoding="UTF-8"?>
<Categories>
<STUX>
<Servers>stuxsh01</Servers>
<Servers>stuxsh03</Servers>
<Servers>stuxsh02</Servers>
<UnitTest>Pass</UnitTest>
</STUX>
<KbnApp>
<Servers>stks01</Servers>
<Servers>stks03</Servers>
<Servers>stks02</Servers>
<UnitTest>Pass</UnitTest>
</KbnApp>
<KbnStorage>
<Servers>stksnfs01</Servers>
<Servers>stksnfs02</Servers>
<UnitTest>Fail</UnitTest>
</KbnStorage>
</Categories>
This transform gives me the result that I want, but I've had to make two templates that are almost identical, wasting lines. I think there should be a way to do this with one template and an xsl:if with an xsl:sort inside it. Can anyone tell me how I would format XSL to do that? Every time I've tried putting an xsl:if the XSL can't be parsed/won't apply and I don't know why. PS I'm SURE there is things I've done here that aren't proper, but by golly I got it to work :) I'm definitely open to learning how to do it better! EDIT: Corrected a typo
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<categories>
<countCategories><xsl:value-of select="count(child::*)" /></countCategories>
<xsl:apply-templates />
</categories>
</xsl:template>
<xsl:template match="KbnApp|KbnStorage">
<Category>
<Name><xsl:value-of select="name()" /></Name>
<countServers><xsl:value-of select="count(Servers)" /></countServers>
<xsl:copy-of select="UnitTest" />
<xsl:for-each select="Servers">
<Server><xsl:value-of select="."/></Server>
</xsl:for-each>
</Category>
</xsl:template>
<xsl:template match="STUX">
<Category>
<Name><xsl:value-of select="name()" /></Name>
<countServers><xsl:value-of select="count(Servers)" /></countServers>
<xsl:copy-of select="UnitTest" />
<xsl:for-each select="Servers">
<xsl:sort order="descending"/>
<Server><xsl:value-of select="."/></Server>
</xsl:for-each>
</Category>
</xsl:template>
</xsl:stylesheet>
For reference...The desired result
<categories>
<countCategories>1</countCategories>
<Category>
<Name>STUX</Name>
<countServers>3</countServers>
<UnitTest>Pass</UnitTest>
<Server>stuxsh03</Server>
<Server>stuxsh02</Server>
<Server>stuxsh01</Server>
</Category>
<Category>
<Name>KbnApp</Name>
<countServers>3</countServers>
<UnitTest>Pass</UnitTest>
<Server>stks01</Server>
<Server>stks03</Server>
<Server>stks02</Server>
</Category>
<Category>
<Name>KbnStorage</Name>
<countServers>2</countServers>
<UnitTest>Fail</UnitTest>
<Server>stksnfs01</Server>
<Server>stksnfs02</Server>
</Category>
</categories>
回答1:
Try changing:
<xsl:sort order="descending"/>
to:
<xsl:sort select="self::*[parent::STUX]" order="descending"/>
Then you can use this in a template that matches all your categories, and have only the STUX
category sorted.
来源:https://stackoverflow.com/questions/64852031/using-xslsort-within-xslif