我对xslt完全陌生。请帮我写样式表。我有这样的输入xml
输入XML:
<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>
所需的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知识不是很好。
答案 0 :(得分:3)
我不是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>
在样本输入上运行时,这也会产生请求的输出。
答案 1 :(得分:0)
啊,在阅读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的解决方案,除了他已经使用密钥添加了优化。