我正在尝试在
XML文件中对一堆记录进行排序.诀窍是我需要为不同的节点使用不同的元素进行排序.举一个最简单的例子,我想这样做:给定一个xml文件
- <?xml version="1.0" encoding="utf-8" ?>
- <buddies>
- <person>
- <nick>Jim</nick>
- <last>Zulkin</last>
- </person>
- <person>
- <first>Joe</first>
- <last>Bumpkin</last>
- </person>
- <person>
- <nick>Pumpkin</nick>
- </person>
- <person>
- <nick>Andy</nick>
- </person>
- </buddies>
我想把它转换成
- Andy
- Joe Bumpkin
- Pumpkin
- Jim Zulkin
也就是说,可以通过名字,姓氏和缺口的任何子集列出人.
排序键是姓氏(如果它存在),否则它是昵称(如果它存在),否则是名字.
我在这里遇到困难,因为使用变量作为xsl:sort键是apparently not allowed.
我目前最好的镜头是进行两步转换:使用此样式表为每条记录添加一个特殊标记
- <?xml version="1.0" encoding="ISO-8859-1"?>
- <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
- <xsl:output omit-xml-declaration="no" indent="yes"/>
- <!-- *** convert each person record into a person2 record w/ the sorting key *** -->
- <xsl:template match="/buddies">
- <buddies>
- <xsl:for-each select="person">
- <person2>
- <xsl:copy-of select="*"/>
- <!-- add the sort-by tag -->
- <sort-by>
- <xsl:choose>
- <xsl:when test="last"> <xsl:value-of select="last"/>
- </xsl:when>
- <xsl:otherwise>
- <xsl:choose>
- <xsl:when test="nick"> <xsl:value-of select="nick"/> </xsl:when>
- <xsl:otherwise> <xsl:value-of select="first"/> </xsl:otherwise>
- </xsl:choose>
- </xsl:otherwise>
- </xsl:choose>
- </sort-by>
- </person2>
- </xsl:for-each>
- </buddies>
然后对生成的xml进行排序
- <?xml version="1.0" encoding="ISO-8859-1"?>
- <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
- <xsl:template match="/buddies">
- <xsl:apply-templates>
- <xsl:sort select="sort-by"/>
- </xsl:apply-templates>
- </xsl:template>
- <xsl:template match="person2">
- <xsl:value-of select="first"/>
- <xsl:value-of select="nick"/>
- <xsl:value-of select="last"/><xsl:text>
- </xsl:text>
- </xsl:template>
虽然这个两步转换有效,但我想知道是否有更优雅的方式一次性完成它?
您可以使用concat XPath函数:
- <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
- <xsl:output method="text"/>
- <xsl:template match="/buddies">
- <xsl:apply-templates>
- <xsl:sort select="concat(last,nick,first)"/>
- </xsl:apply-templates>
- </xsl:template>
- <xsl:template match="person">
- <xsl:value-of select="concat(normalize-space(concat(first,' ',last)),'
')"/>
- </xsl:template>
- </xsl:stylesheet>