xslt 具有父节点的递归子节点
Posted
技术标签:
【中文标题】xslt 具有父节点的递归子节点【英文标题】:xslt recursive child nodes with parent node 【发布时间】:2017-05-04 08:44:34 【问题描述】:我想知道在 xslt 2.0 中解决此解决方案的更好方法。
输入:
<Root>
<Record>
<FName>Abc</FName>
<MName>FAbc</MName>
<Kid>
<CName>C1Abc<CName>
</Kid>
<Kid>
<CName>C2Abc<CName>
</Kid>
</Record>
<Record>
<FName>Def</FName>
<MName>FDef</MName>
<Kid>
<CName>C1Def<CName>
</Kid>
</Record>
<Record>
<FName>Xyz</FName>
<MName>FXyz</MName>
</Record>
</Root>
输出:
<Root>
<Record>
<FName>Abc</FName>
<MName>FAbc</MName>
<CName>C1Abc<CName>
</Record>
<Record>
<FName>Abc</FName>
<MName>FAbc</MName>
<CName>C2Abc<CName>
</Record>
<Record>
<FName>Def</FName>
<MName>FDef</MName>
<CName>C1Def<CName>
</Record>
<Record>
<FName>Xyz</FName>
<MName>FXyz</MName>
<CName></CName>
</Record>
</Root>
XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
version="2.0">
<xsl:template match="Root">
<Root>
<xsl:apply-templates select="Record">
</xsl:apply-templates>
</Root>
</xsl:template>
<xsl:template match="Record">
<xsl:choose>
<xsl:when test="Kid">
<xsl:apply-templates select="Kid">
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<Record>
<FName>
<xsl:value-of select="FName"/>
</FName>
<MName>
<xsl:value-of select="MName"/>
</MName>
<CName>
<xsl:value-of select="Kid/CName"/>
</CName>
</Record>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="Kid">
<Record>
<FName>
<xsl:value-of select="../FName"/>
</FName>
<MName>
<xsl:value-of select="../MName"/>
</MName>
<CName>
<xsl:value-of select="CName"/>
</CName>
</Record>
</xsl:template>
</xsl:stylesheet>
我的 xslt 工作正常,我能够得到我期望的输出。但我想听听是否有其他更好的方法来做到这一点。主要是为了避免任何性能问题,因为将有数千条记录和更多数据。谢谢。
【问题讨论】:
会一直存在FName
和MName
吗?或者任何子元素都可以是可选的?
你真的有性能问题吗?您是否使用 XSLT 处理器分析了现有代码以找出需要改进的代码?
@Tim C,所有子元素都是可选的,但如果没有值,则应该有一个空标签 你可以重写
<xsl:template match="Record">
<xsl:choose>
<xsl:when test="Kid">
<xsl:apply-templates select="Kid">
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<Record>
<FName>
<xsl:value-of select="FName"/>
</FName>
<MName>
<xsl:value-of select="MName"/>
</MName>
<CName>
<xsl:value-of select="Kid/CName"/>
</CName>
</Record>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
作为
<xsl:template match="Record[not(Kid)]">
<Record>
<FName>
<xsl:value-of select="FName"/>
</FName>
<MName>
<xsl:value-of select="MName"/>
</MName>
<CName></CName>
</Record>
</xsl:template>
<xsl:template match="Record[Kid]">
<xsl:apply-templates select="Kid"/>
</xsl:template>
【讨论】:
感谢马丁的评论。顺便说一句,是否有地方可以重写 ../ (从当前节点移回)或者这是正确的方法? 我认为没有必要用..
重写对父节点的访问。我建议的重写也主要是装饰性的,但总的来说,我认为使用带有谓词的模板匹配模式来区分不同的结构比在单个模板中使用 xsl:choose/xsl:when
更清晰、更优雅。以上是关于xslt 具有父节点的递归子节点的主要内容,如果未能解决你的问题,请参考以下文章
XSLT 将具有父节点的节点移动到具有给定属性的每个父节点的兄弟节点中