好的,基于这个问题XSLT 1.0 sort elements我无法弄清楚为什么以下不起作用:
我有以下XML:
<?xml version="1.0" encoding="UTF-8"?>
<viewentries>
<viewentry>
<entrydata name="Waste">
<text>Bric-a-Brac</text>
</entrydata>
<entrydata name="Disposal">
<text/>
</entrydata>
</viewentry>
<viewentry>
<entrydata name="Waste">
<textlist>
<text>Paper</text>
<text>Glass</text>
</textlist>
</entrydata>
<entrydata name="Disposal">
<text/>
</entrydata>
</viewentry>
<viewentry>
<entrydata name="Waste">
<textlist>
<text>Paper</text>
<text>Cans</text>
</textlist>
</entrydata>
<entrydata name="Disposal">
<text>Washing Machines</text>
<text>Cars</text>
</entrydata>
</viewentry>
</viewentries>
以下XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="k1" match="entrydata[@name = 'Waste' or @name = 'Disposal']//text" use="concat(ancestor::entrydata/@name, '|', .)"/>
<xsl:template match="viewentries">
<categories>
<xsl:apply-templates/>
</categories>
</xsl:template>
<xsl:template match="viewentry">
<xsl:apply-templates select="entrydata[@name = 'Waste' or @name = 'Disposal']//text
[generate-id() = generate-id(key('k1', concat(ancestor::entrydata/@name, '|', .))[1])]">
<xsl:sort select="."/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="text[normalize-space() != '']">
<category type="{ancestor::entrydata/@name}">
<xsl:apply-templates/>
</category>
</xsl:template>
</xsl:stylesheet>
这给出了以下输出:
<?xml version="1.0" encoding="UTF-8"?>
<categories>
<category type="Waste">Bric-a-Brac</category>
<category type="Waste">Glass</category>
<category type="Waste">Paper</category>
<category type="Waste">Cans</category>
<category type="Disposal">Cars</category>
<category type="Disposal">Washing Machines</category>
</categories>
我需要按排序顺序输出:
<?xml version="1.0" encoding="UTF-8"?>
<categories>
<category type="Waste">Bric-a-Brac</category>
<category type="Waste">Cans</category>
<category type="Disposal">Cars</category>
<category type="Waste">Glass</category>
<category type="Waste">Paper</category>
<category type="Disposal">Washing Machines</category>
</categories>
我做错了什么?
修改
似乎只根据<text>
的{{1}}值而不是所有<entrydata>
值进行排序。
但是这个样式表工作正常:
<text>
有人可以解释为什么第一个例子不起作用,但第二个例子没有用。
答案 0 :(得分:2)
任何人都可以解释为什么将排序应用于第一个模板, 但是当它应用于我原来的第二个模板时 问题不是????
这是您的“第二个模板”:
<xsl:template match="text[normalize-space() != '']">
<category type="{ancestor::entrydata/@name}">
<xsl:apply-templates>
<xsl:sort select="."/>
</xsl:apply-templates>
</category>
</xsl:template>
在这里,您希望按字符串值对当前节点的子节点进行排序。
但是,在提供的XML文档中,任何text
元素都有一个文本节点子元素 - 因此没有任何要排序的东西!
在此问题和上一个问题中,您提交了相同的错误 - 尝试对必须排序的元素的子项进行排序 - 您排序太晚了。
<强>记住强>:
<xsl:apply-templates/>
是的缩写:
<xsl:apply-templates select="child::node()"/>
所以,这意味着:将模板应用于我的孩子“ - 不是”将模板应用于我“。
更新:以下是解决问题的正确方法:
<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="kCatVal" match="text[text()]" use="concat(../@name, '+', .)"/>
<xsl:template match="/">
<categories>
<xsl:apply-templates select=
"//text[generate-id()
=
generate-id(key('kCatVal',
concat(../@name, '+', .)
)[1]
)
]">
<xsl:sort/>
</xsl:apply-templates>
</categories>
</xsl:template>
<xsl:template match="text">
<category type="{../@name}"><xsl:value-of select="."/></category>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档:
<viewentries>
<viewentry>
<entrydata name="Waste">
<text>Bric-a-Brac</text>
</entrydata>
<entrydata name="Disposal">
<text/>
</entrydata>
</viewentry>
<viewentry>
<entrydata name="Waste">
<textlist>
<text>Paper</text>
<text>Glass</text>
</textlist>
</entrydata>
<entrydata name="Disposal">
<text/>
</entrydata>
</viewentry>
<viewentry>
<entrydata name="Waste">
<textlist>
<text>Paper</text>
<text>Cans</text>
</textlist>
</entrydata>
<entrydata name="Disposal">
<text>Washing Machines</text>
<text>Cars</text>
</entrydata>
</viewentry>
</viewentries>
产生了想要的正确结果:
<categories>
<category type="Waste">Bric-a-Brac</category>
<category type="">Cans</category>
<category type="Disposal">Cars</category>
<category type="">Glass</category>
<category type="">Paper</category>
<category type="Disposal">Washing Machines</category>
</categories>
解释:
这种分组需要基于具有两个部分的复合键进行索引。因此,use
的{{1}}属性被指定为这两个部分的串联,由我们知道不能出现在任何值中的字符连接在一起(以避免在值为0时出现误报)第一个关键组件是第二个关键组件的值的前缀。)