采用此question about beautiful XSL,但更具体地,我应该如何重构此XSL以利用应用模板和/或键。
我倾向于“过度使用”for-each元素来控制源代码的上下文,我可以想象apply-templates会有所帮助。尽管谷歌搜索了很多次,我仍然不明白如何在多个模板中控制上下文。
在下面的示例中,如何通过重构减少重复的XPath段?
<xsl:template match="/">
<xsl:element name="Body">
<xsl:element name="Person">
<xsl:if test="/source/dbSrc/srv/v[@name='name']/text()='false'">
<xsl:element name="PhoneNumber" />
<xsl:element name="Zip">
<xsl:value-of
select="/source/req[1]/personal-info/address-info/zip-code" />
</xsl:element>
</xsl:if>
<xsl:if test="/source/dbSrc/srv/v[@name='name']/text()='true'">
<xsl:element name="PhoneNumber" />
<xsl:element name="Zip">
<xsl:value-of select="/source/req[3]/personal-info/address-info/zip-code" />
</xsl:element>
</xsl:if>
</xsl:element>
</xsl:template>发布于 2011-03-03 15:09:39
重构给定代码的一种初始方法如下:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<Body>
<Person>
<PhoneNumber/>
<Zip>
<xsl:apply-templates select=
"/*/dbSrc/srv/v[@name='name']"/>
</Zip>
</Person>
</Body>
</xsl:template>
<xsl:template match="v[@name='name' and .='true']">
<xsl:value-of select=
"/*/req[3]/personal-info/address-info/zip-code"/>
</xsl:template>
<xsl:template match="v[@name='name' and .='false']">
<xsl:value-of select=
"/*/req[1]/personal-info/address-info/zip-code"/>
</xsl:template>
</xsl:stylesheet>xslt请注意:重构后的代码不包含任何条件指令。
的进一步重构可以让我们摆脱最后一个模板,因为在这种情况下实际上不需要额外的模板--代码只创建一个元素,并且依赖于一个条件:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:variable name="vCond" select=
"/*/dbSrc/srv/v[@name='name']/text()='true'"/>
<xsl:variable name="vInd" select=
"3*$vCond + 1*not($vCond)"/>
<xsl:template match="/">
<Body>
<Person>
<PhoneNumber/>
<Zip>
<xsl:value-of select=
"/*/req[position()=$vInd]
/personal-info/address-info/zip-code"/>
</Zip>
</Person>
</Body>
</xsl:template>
</xsl:stylesheet>注意::这里我们假设/*/dbSrc/srv/v[@name='name']/text()只能有两个可能的值:'true'或'false'
发布于 2011-03-03 17:07:50
在XSLT 2.0中,我会这样写:
<xsl:template match="/">
<Body>
<Person>
<PhoneNumber/>
<Zip>
<xsl:variable name="index" as="xs:integer"
select="if (/source/dbSrc/srv/v[@name='name']='true') then 3 else 1"/>
<xsl:value-of select="/source/req[$index]/personal-info/address-info/zip-code"/>
</Zip>
</Person>
</Body>
</xsl:template>在1.0版本中,xsl:变量变得有点复杂,但在其他方面都是一样的。
注意使用文字结果元素和变量来减小代码的大小;还要避免使用"/text()",这几乎总是不好的做法。
在这里使用模板规则几乎没有什么用处,因为您使用的输入数据非常少,而且您似乎确切知道在哪里可以找到它。如果您想不那么严格地了解您在源代码中的确切位置,模板规则将发挥作用:它们有助于使代码对输入中的可变性和更改更具弹性。但是在没有看到源代码和更多的背景知识的情况下,我们不能告诉你哪里需要这种灵活性。对我来说,索引"1“和"3”的硬编码看起来像是一个危险的信号,但只有你才能做出判断。
https://stackoverflow.com/questions/5173488
复制相似问题