使用xslt将xml转换为xml:递归匹配&;创建类层次树
我对xslt一无所知。请帮我写样式表。我有这样的xml输入 输入XML:使用xslt将xml转换为xml:递归匹配&;创建类层次树,xslt,xslt-1.0,Xslt,Xslt 1.0,我对xslt一无所知。请帮我写样式表。我有这样的xml输入 输入XML: <elements> <e1> <pid>1</pid> <cid>2</cid> </e1> <e1> <pid>1</pid> <cid>3</cid> </e1>
<elements>
<e1>
<pid>1</pid>
<cid>2</cid>
</e1>
<e1>
<pid>1</pid>
<cid>3</cid>
</e1>
<e1>
<pid>2</pid>
<cid>4</cid>
</e1>
</elements>
1.
2.
1.
3.
2.
4.
所需的XML:
<tree>
<unit id="1">
<unit id="2">
<unit id="4">
<data></data>
</unit>
<data></data>
</unit>
<unit id="3">
<data></data>
</unit>
<data></data>
</unit>
</tree>
我觉得这应该很容易,但我正在努力寻找如何做到这一点的信息。我的XSLT知识不是很好。我不能100%确定您希望XSLT如何从该输入确定top id为1(是因为它是唯一的
pid
值,没有相应的cid
值,还是始终为1?)。尽管如此,这项工作还是应该做到:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="kItemsByC" match="e1" use="cid" />
<xsl:key name="kItemsByP" match="e1" use="pid" />
<xsl:template match="/">
<tree>
<xsl:call-template name="Unit">
<!-- This will be the value of the <pid> that has no <cid> references to
it (assuming there is only one top-level <pid>) -->
<xsl:with-param name="id"
select="string(/elements/e1/pid[not(key('kItemsByC', .))])" />
</xsl:call-template>
</tree>
</xsl:template>
<xsl:template match="e1" name="Unit">
<xsl:param name="id" select="cid" />
<unit id="{$id}">
<xsl:apply-templates select="key('kItemsByP', $id)" />
<data />
</unit>
</xsl:template>
</xsl:stylesheet>
当对示例输入运行此操作时,将生成:
<tree>
<unit id="1">
<unit id="2">
<unit id="4">
<data />
</unit>
<data />
</unit>
<unit id="3">
<data />
</unit>
<data />
</unit>
</tree>
注意:上述XSLT具有尝试动态定位顶级ID的逻辑。如果可以假设顶级单元始终具有ID 1,则可以消除一个键和上述XSLT(有些)复杂的公式:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="kItemsByP" match="e1" use="pid" />
<xsl:template match="/">
<tree>
<xsl:call-template name="Unit">
<xsl:with-param name="id" select="1" />
</xsl:call-template>
</tree>
</xsl:template>
<xsl:template match="e1" name="Unit">
<xsl:param name="id" select="cid" />
<unit id="{$id}">
<xsl:apply-templates select="key('kItemsByP', $id)" />
<data />
</unit>
</xsl:template>
</xsl:stylesheet>
当在示例输入上运行时,这也会生成所请求的输出。啊,在阅读JLRishe之后,我想我明白了:“pid”表示“父ID”,“cid”表示“子ID”,e1表示父子关系。出色的侦探工作,我永远不会为自己解决这个问题 基本模型是,当您定位在父元素上时,会将模板应用于其子元素。如果父/子关系由主键/外键表示,就像它们使用XML层次结构表示一样,这同样适用。因此,其实质是:
<xsl:template match="e1">
<unit id="{pid}">
<xsl:apply-templates select="//e1[pid=current()/cid]"/>
<data/>
</unit>
</xsl:template>
这本质上是JLRishe的解决方案,除了他添加了一个使用密钥的优化