以下是示例xml
<Data version="2.0">
<Group>
<Item>3</Item>
<Item>1</Item>
<Item>2</Item>
</Group>
<Group>
<Item>7</Item>
<Item>5</Item>
</Group>
</Data>
为了按Group by Item值排序节点,我尝试使用以下xsl:
<xsl:template match="/Data">
<xsl:apply-templates select="Group">
<xsl:sort select="Item" />
</xsl:apply-templates>
</xsl:template>
但是只获取值,即使没有排序:
3
1
2
7
5
所以问题是:1。为什么排序不起作用2.如何保留所有节点并保持xml的结构?
答案 0 :(得分:4)
这就是你想要的:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Group">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="Item">
<xsl:sort select="text()" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
第一个模板是“身份模板”(Google it),它将输入复制到输出不变。然后,对于Group节点,我们将其复制到输出(<xsl:copy>
),复制其属性,然后在对它们进行排序后复制嵌套的Item节点。它们被复制,因为内部<xsl:apply-templates select="Item">
最终使用Identity模板,因为Item节点没有更具体的模板。
请注意,如果Group
个节点可以包含Item
个节点以外的其他内容,则必须确保它也被复制。上面的模板会丢弃它们。
答案 1 :(得分:2)
@ Jim的答案基本上是正确的。
但是,应用于稍微更现实的XML文档,例如:
<Data version="2.0">
<Group>
<Item>3</Item>
<Item>1</Item>
<Item>10</Item>
<Item>2</Item>
</Group>
<Group>
<Item>7</Item>
<Item>5</Item>
</Group>
</Data>
产生的结果显然不你想要什么(10在2和3之前出现):
<?xml version="1.0" encoding="utf-8"?>
<Data version="2.0">
<Group>
<Item>1</Item>
<Item>10</Item>
<Item>2</Item>
<Item>3</Item>
</Group>
<Group>
<Item>5</Item>
<Item>7</Item>
</Group>
</Data>
这是一个正确的解决方案(也略短):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Group">
<Group>
<xsl:apply-templates select="*">
<xsl:sort data-type="number"/>
</xsl:apply-templates>
</Group>
</xsl:template>
</xsl:stylesheet>
将此转换应用于同一XML文档(上图)时,会生成所需的正确结果:
<Data version="2.0">
<Group>
<Item>1</Item>
<Item>2</Item>
<Item>3</Item>
<Item>10</Item>
</Group>
<Group>
<Item>5</Item>
<Item>7</Item>
</Group>
</Data>
说明:使用 <xsl:sort>
的data-type
属性指定排序键值应视为数字,而不是(默认的)字符串。