xml – 从XSLT中的路径创建嵌套树结构
发布时间:2020-12-16 07:43:29 所属栏目:百科 来源:网络整理
导读:我有一个动态的 XML文档,它表示一个类别的树结构,但这样做是以任意顺序使用路径分隔的属性,如下所示: data record ID="24" Name="category 1sub category 1"/ record ID="26" Name="category 1"/ record ID="25" Name="category 1sub category 1sub cate
我有一个动态的
XML文档,它表示一个类别的树结构,但这样做是以任意顺序使用路径分隔的属性,如下所示:
<data> <record ID="24" Name="category 1sub category 1"/> <record ID="26" Name="category 1"/> <record ID="25" Name="category 1sub category 1sub category 2"/> <record ID="27" Name="category 1sub category 1sub category 3"/> ... </data> 我需要提出一个解决方案,使XML标准化,以便将其转换成如下所示: <data> <record ID="26" Name="category 1"> <record ID="24" Name="sub category 1"> <record ID="25" Name="sub category 2"/> <record ID="27" Name="sub category 3"/> </record> </record> ... </data> 基本上我想知道这是否是XSLT可能解决的问题,以及如何,而不是以编程方式进行.
好没问题:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > <xsl:output indent="yes" /> <xsl:template match="/data"> <!-- copy the document element --> <xsl:copy> <!-- That's where we start: all "record" nodes that have no "". --> <xsl:apply-templates mode="recurse" select="/data/record[ not(contains(@Name,'')) ]" /> </xsl:copy> </xsl:template> <xsl:template match="record" mode="recurse"> <xsl:param name="starting-path" select="''" /> <!-- The record node and its ID attribute can be copied. --> <xsl:copy> <xsl:copy-of select="@ID" /> <!-- Create the new "name" attribute. --> <xsl:attribute name="Name"> <xsl:value-of select="substring-after(@Name,$starting-path)" /> </xsl:attribute> <!-- Append a backslash to the current path. --> <xsl:variable name="current-path" select="concat(@Name,'')" /> <!-- Select all "record" nodes that are one level deeper... --> <xsl:variable name="children" select="/data/record[ starts-with(@Name,$current-path) and not(contains(substring-after(@Name,$current-path),'')) ]" /> <!-- ...and apply this template to them. --> <xsl:apply-templates mode="recurse" select="$children"> <xsl:with-param name="starting-path" select="$current-path" /> </xsl:apply-templates> </xsl:copy> </xsl:template> </xsl:stylesheet> 我的系统输出: <data> <record ID="26" Name="category 1"> <record ID="24" Name="sub category 1"> <record ID="25" Name="sub category 2"></record> <record ID="27" Name="sub category 3"></record> </record> </record> </data> 请注意,整个解决方案是基于以下假设:所有路径都是规范的,不包含尾随的反斜杠. 还要注意,任何不匹配的/孤立的“记录”元素都不会在输出中(除非当然是根级别). 还有一件事:模板模式(“递归”)并不是绝对必要的.我包括它,因为模板正在做一些比较特别的事情,并且可能有机会在你的解决方案中有一个匹配“记录”节点的模板.在这种情况下,这个解决方案可以放在没有任何其他的东西.对于独立解决方案,可以随时删除模板模式. 呵呵,最后一件事情是:如果你希望结果文件按照Name命名,请使用< xsl:apply-templates> (两次出现),像这样: <xsl:apply-templates select="..."> <xsl:sort select="@Name" data-type="text" order="ascending" /> </xsl:apply-templates> (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |