我们的一项服务提供了一个列出todo集合的xml文档。 Todo的结构可以在一个todolist下嵌套。每个todo item
都有父todo list
。我需要使用XSL来显示当前父todo-list
的待办事项数量。请在下面找到xml的结构
<TodoListCollection>
<TodoList>
<Id>1</Id>
<ParentId></ParentId>
<Count>3</Count>
<TodoItemCollection>
<TodoItem></TodoItem>
<TodoItem></TodoItem>
<TodoItem></TodoItem>
</TodoItemCollection>
</TodoList>
<TodoList>
<Id>2</Id>
<ParentId>1</ParentId>
<Count>4</Count>
<TodoItemCollection>
<TodoItem></TodoItem>
<TodoItem></TodoItem>
<TodoItem></TodoItem>
<TodoItem></TodoItem>
</TodoItemCollection>
</TodoList>
</TodoListCollection>
在TodoList ID = 1
的第一次迭代中,我应该能够统计为3 + 4 = 7
。因为在第一个待办事项集合中有 3 ,而在子项目集项目集合中有 4 (ParentId = 1
)。这里的嵌套只是一个层次,但我们将其设计为N级。
答案 0 :(得分:2)
此转化:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kChildren" match="TodoList" use="ParentId"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<xsl:variable name="vrtfPass1">
<xsl:copy>
<xsl:apply-templates select="key('kChildren', '')"/>
</xsl:copy>
</xsl:variable>
<xsl:variable name="vPass1" select="ext:node-set($vrtfPass1)"/>
<xsl:apply-templates select="$vPass1/*" mode="pass2"/>
</xsl:template>
<xsl:template match="TodoList">
<xsl:copy>
<xsl:apply-templates />
<xsl:apply-templates select="key('kChildren', Id)"/>
</xsl:copy>
</xsl:template>
<xsl:template match="node()|@*" mode="pass2">
<xsl:copy>
<xsl:apply-templates select="node()|@*" mode="pass2"/>
</xsl:copy>
</xsl:template>
<xsl:template match="TodoList" mode="pass2">
<xsl:copy>
<xsl:apply-templates select="*[not(self::TodoList)]" mode="pass2"/>
</xsl:copy>
<xsl:apply-templates select="TodoList" mode="pass2"/>
</xsl:template>
<xsl:template match="Count" mode="pass2">
<Count>
<xsl:value-of select="sum(..//Count)"/>
</Count>
</xsl:template>
</xsl:stylesheet>
应用于以下XML文档(基于提供的,但具有更深层次结构):
<TodoListCollection>
<TodoList>
<Id>1</Id>
<ParentId></ParentId>
<Count>3</Count>
<TodoItemCollection>
<TodoItem></TodoItem>
<TodoItem></TodoItem>
<TodoItem></TodoItem>
</TodoItemCollection>
</TodoList>
<TodoList>
<Id>2</Id>
<ParentId>1</ParentId>
<Count>7</Count>
<TodoItemCollection>
<TodoItem></TodoItem>
<TodoItem></TodoItem>
<TodoItem></TodoItem>
<TodoItem></TodoItem>
</TodoItemCollection>
</TodoList>
<TodoList>
<Id>3</Id>
<ParentId>2</ParentId>
<Count>5</Count>
<TodoItemCollection>
<TodoItem></TodoItem>
<TodoItem></TodoItem>
<TodoItem></TodoItem>
<TodoItem></TodoItem>
</TodoItemCollection>
</TodoList>
<TodoList>
<Id>4</Id>
<ParentId>3</ParentId>
<Count>3</Count>
<TodoItemCollection>
<TodoItem></TodoItem>
<TodoItem></TodoItem>
<TodoItem></TodoItem>
<TodoItem></TodoItem>
</TodoItemCollection>
</TodoList>
<TodoList>
<Id>5</Id>
<ParentId>2</ParentId>
<Count>1</Count>
<TodoItemCollection>
<TodoItem></TodoItem>
<TodoItem></TodoItem>
<TodoItem></TodoItem>
<TodoItem></TodoItem>
</TodoItemCollection>
</TodoList>
</TodoListCollection>
生成想要的正确结果:
<TodoListCollection>
<TodoList>
<Id>1</Id>
<ParentId/>
<Count>19</Count>
<TodoItemCollection>
<TodoItem/>
<TodoItem/>
<TodoItem/>
</TodoItemCollection>
</TodoList>
<TodoList>
<Id>2</Id>
<ParentId>1</ParentId>
<Count>16</Count>
<TodoItemCollection>
<TodoItem/>
<TodoItem/>
<TodoItem/>
<TodoItem/>
</TodoItemCollection>
</TodoList>
<TodoList>
<Id>3</Id>
<ParentId>2</ParentId>
<Count>8</Count>
<TodoItemCollection>
<TodoItem/>
<TodoItem/>
<TodoItem/>
<TodoItem/>
</TodoItemCollection>
</TodoList>
<TodoList>
<Id>4</Id>
<ParentId>3</ParentId>
<Count>3</Count>
<TodoItemCollection>
<TodoItem/>
<TodoItem/>
<TodoItem/>
<TodoItem/>
</TodoItemCollection>
</TodoList>
<TodoList>
<Id>5</Id>
<ParentId>2</ParentId>
<Count>1</Count>
<TodoItemCollection>
<TodoItem/>
<TodoItem/>
<TodoItem/>
<TodoItem/>
</TodoItemCollection>
</TodoList>
</TodoListCollection>
<强>解释强>:
这是一个两遍转换:
在第一遍中,文档根据父文件从平面转换为分层 - &gt; id relation。
在第二遍中,pass1的结果将转换回平面文档。调整Count
个元素以包含其最里面包含子树中所有Count
个元素的总和。
如果我们希望最终结果包含按TodoList
排序的Id
元素,则可能需要第三次传递。