嗨,我有一个简单的XSL样式表,它可以从一个平面XML文件构建一个嵌套列表(该文件必须是平面的-这是软件输出它的方式)。
但是,在列表末尾,它重复了所有项目,我不明白为什么。我仅限使用XSL V1.0。
XML:
<QueryResults ReportName="Document Hierarchy Visio" ReportID="216">
<Data RecordCount="186">
<DataRow index="1">
<parentid_visio></parentid_visio>
<childid_visio>111</childid_visio>
<parent_id>1</parent_id>
<child_id>1</child_id>
<formname>Patient</formname>
<lvl>1</lvl>
<patrank>1</patrank>
</DataRow>
<DataRow index="2">
<parentid_visio>111</parentid_visio>
<childid_visio>213</childid_visio>
<parent_id>1</parent_id>
<child_id>3</child_id>
<formname>Alias</formname>
<lvl>2</lvl>
<patrank>1</patrank>
</DataRow>
<DataRow index="3">
<parentid_visio>111</parentid_visio>
<childid_visio>214</childid_visio>
<parent_id>1</parent_id>
<child_id>4</child_id>
<formname>Address</formname>
<lvl>2</lvl>
<patrank>1</patrank>
</DataRow>
</Data>
</QueryResults>
XSL:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="child" match="DataRow" use="parentid_visio" />
<xsl:template match="Data">
<div class="tree">
<ul>
<xsl:apply-templates select="DataRow[not(DataRow/parentid_visio)]"/>
</ul>
</div>
</xsl:template>
<xsl:template match="DataRow">
<li>
<a href="#"><xsl:value-of select="formname"/></a>
<xsl:if test="key('child', childid_visio)">
<ul>
<xsl:apply-templates select="key('child', childid_visio)[not(DataRow/parentid_visio)]"/>
</ul>
</xsl:if>
</li>
</xsl:template>
</xsl:stylesheet>
它应该输出
<div class="tree">
<ul>
<li><a href="#">Patient</a>
<ul>
<li><a href="#">Alias</a></li>
<li><a href="#">Address</a></li>
<li><a href="#">Alert</a></li>
<li><a href="#">Contact</a></li>
<li><a href="#">GP Detail</a></li>
<li><a href="#">School Detail</a></li>
<li><a href="#">Other Agency</a></li>
</ul>
</li>
</ul>
</div>
但返回:
<div class="tree">
<ul>
<li><a href="#">Patient</a><ul>
<li><a href="#">Alias</a></li>
<li><a href="#">Address</a></li>
<li><a href="#">Alert</a></li>
<li><a href="#">Contact</a></li>
<li><a href="#">GP Detail</a></li>
<li><a href="#">School Detail</a></li>
<li><a href="#">Other Agency</a></li>
</ul>
</li>
<li><a href="#">Alias</a></li>
<li><a href="#">Address</a></li>
<li><a href="#">Alert</a></li>
<li><a href="#">Contact</a></li>
<li><a href="#">GP Detail</a></li>
<li><a href="#">School Detail</a></li>
<li><a href="#">Other Agency</a></li>
</ul>
</div>
我要去哪里错了?我不确定为什么最后会重复这个过程。 这是一些额外的文字,因为stackoverflow不允许我发布,因为显然需要更多详细信息。
答案 0 :(得分:0)
问题出在这条线上。...
<xsl:apply-templates select="DataRow[not(DataRow/parentid_visio)]"/>
这是说“选择没有DataRow
的任何DataRow/parentid_visio
作为孩子”。但是,XML中没有DataRow
甚至没有DataRow
作为子元素,因此它选择了所有行。
因此,您可以将其更改为此,因此它仅将parentid_visio
作为子项进行检查:
<xsl:apply-templates select="DataRow[not(parentid_visio)]"/>
但是这不起作用,因为这会检查节点是否存在,而不管该节点是否有文本,因此它<parentid_visio></parentid_visio>
返回true,并且没有选择任何行。
您还需要执行此操作,以检查是否有空的parentid_visio
节点以及不存在的节点
<xsl:apply-templates select="DataRow[not(parentid_visio) or parentid_visio = '']"/>
或者这样做也可以
<xsl:apply-templates select="DataRow[not(parentid_visio != '')]"/>
或者,如果您知道parentid_visio
将永远存在...
<xsl:apply-templates select="DataRow[parentid_visio = '']"/>
(在最后一种情况下,如果XML中不存在parentid_visio
,则parentid_visio = ''
返回false,因此该行将不会被选中)。