我正在使用xslt(版本1.0,使用MSXSL)转换一些xml。
假设我的xml数据如下所示:
<table>
<record><name>A</name><value>a</value><size>10</size></record>
<record><name>A</name><value>b</value><size>35</size></record>
<record><name>A</name><value>c</value><size>60</size></record>
<record><name>B</name><value>x</value><size>15</size></record>
<record><name>B</name><value>y</value><size>90</size></record>
<record><name>B</name><value>z</value><size>20</size></record>
...
</table>
我的目标是:
<name>
<size>
,比如maxsize
maxsize
(降序)结果可能是:
<table>
<group>B<maxsize>90</maxsize>
<record><value>x</value><size>15</size>
<record><value>y</value><size>90</size>
<record><value>z</value><size>20</size>
</group>
<group>A<maxsize>60</maxsize>
<record><value>a</value><size>10</size>
<record><value>a</value><size>35</size>
<record><value>a</value><size>60</size>
</group>
</table>
现在步骤1,2和4,我可以做到。但是......我如何按照最大尺寸订购这些组呢?
我尝试在包含组的变量中构建新节点集。我可以构建这样一个集合,但我只能以字符串形式访问它。
应该可以,对吧?
答案 0 :(得分:1)
你走了:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:key name="kRecord" match="record" use="name"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<xsl:copy>
<xsl:apply-templates
select="record[generate-id() =
generate-id(key('kRecord', name)[1])]"
mode="group">
<xsl:sort select="key('kRecord', name)/size
[not(. < key('kRecord', ../name)/size)]"
data-type="number"
order="descending" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="record" mode="group">
<xsl:variable name="members" select="key('kRecord', name)" />
<group>
<xsl:value-of select="name" />
<maxsize>
<xsl:value-of select="$members/size[not(. < $members/size)]"/>
</maxsize>
<xsl:apply-templates select="$members" />
</group>
</xsl:template>
<xsl:template match="record/name" />
</xsl:stylesheet>
在样本输入上运行时,结果为:
<table>
<group>
B<maxsize>90</maxsize><record>
<value>x</value>
<size>15</size>
</record><record>
<value>y</value>
<size>90</size>
</record><record>
<value>z</value>
<size>20</size>
</record>
</group>
<group>
A<maxsize>60</maxsize><record>
<value>a</value>
<size>10</size>
</record><record>
<value>b</value>
<size>35</size>
</record><record>
<value>c</value>
<size>60</size>
</record>
</group>
</table>
顺便提一下,如果使用大多数XSLT处理器中可用的node-set()
函数,则可以访问变量中构造的节点集。我喜欢尽可能避免使用node-set()
函数,因为它是非标准的并且没有完全的支持(并且它的名称空间在支持它的处理器之间甚至不一致),但是你可以这样做它:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exslt="http://exslt.org/common"
exclude-result-prefixes="exslt">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:key name="kRecord" match="record" use="name"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/table">
<xsl:copy>
<xsl:variable name="groups">
<xsl:apply-templates
select="record[generate-id() =
generate-id(key('kRecord', name)[1])]"
mode="group" />
</xsl:variable>
<xsl:apply-templates select="exslt:node-set($groups)/*">
<xsl:sort select="maxsize" data-type="number" order="descending" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="record" mode="group">
<xsl:variable name="members" select="key('kRecord', name)" />
<group>
<xsl:value-of select="name" />
<maxsize>
<xsl:apply-templates select="$members/size" mode="max">
<xsl:sort select="." data-type="number" order="descending" />
</xsl:apply-templates>
</maxsize>
<xsl:apply-templates select="$members" />
</group>
</xsl:template>
<xsl:template match="record/name" />
<xsl:template match="*" mode="max">
<xsl:if test="position() = 1">
<xsl:value-of select="." />
</xsl:if>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)
这个简短的转换(只有两个模板,没有模式,没有变量):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:key name="kRecByName" match="record" use="name"/>
<xsl:template match="/*">
<table>
<xsl:apply-templates select=
"*[generate-id()=generate-id(key('kRecByName', name)
[not(key('kRecByName', name)/size > size)][1])]">
<xsl:sort select="size" data-type="number" order="descending"/>
</xsl:apply-templates>
</table>
</xsl:template>
<xsl:template match="record">
<group><xsl:value-of select="name"/><maxsize><xsl:value-of select="size"/></maxsize>
<xsl:copy-of select="key('kRecByName', name)"/>
</group>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档:
<table>
<record><name>A</name><value>a</value><size>10</size></record>
<record><name>A</name><value>b</value><size>35</size></record>
<record><name>A</name><value>c</value><size>60</size></record>
<record><name>B</name><value>x</value><size>15</size></record>
<record><name>B</name><value>y</value><size>90</size></record>
<record><name>B</name><value>z</value><size>20</size></record>
...
</table>
生成想要的正确结果:
<table>
<group>B<maxsize>90</maxsize>
<record>
<name>B</name>
<value>x</value>
<size>15</size>
</record>
<record>
<name>B</name>
<value>y</value>
<size>90</size>
</record>
<record>
<name>B</name>
<value>z</value>
<size>20</size>
</record>
</group>
<group>A<maxsize>60</maxsize>
<record>
<name>A</name>
<value>a</value>
<size>10</size>
</record>
<record>
<name>A</name>
<value>b</value>
<size>35</size>
</record>
<record>
<name>A</name>
<value>c</value>
<size>60</size>
</record>
</group>
</table>