首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何重构此XSL以利用apply-templates?

如何重构此XSL以利用apply-templates?
EN

Stack Overflow用户
提问于 2011-03-03 05:07:07
回答 2查看 212关注 0票数 3

采用此question about beautiful XSL,但更具体地,我应该如何重构此XSL以利用应用模板和/或键。

我倾向于“过度使用”for-each元素来控制源代码的上下文,我可以想象apply-templates会有所帮助。尽管谷歌搜索了很多次,我仍然不明白如何在多个模板中控制上下文。

在下面的示例中,如何通过重构减少重复的XPath段?

代码语言:javascript
复制
    <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>
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-03-03 15:09:39

重构给定代码的一种初始方法如下:

代码语言:javascript
复制
<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请注意:重构后的代码不包含任何条件指令。

的进一步重构可以让我们摆脱最后一个模板,因为在这种情况下实际上不需要额外的模板--代码只创建一个元素,并且依赖于一个条件:

代码语言:javascript
复制
<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'

票数 1
EN

Stack Overflow用户

发布于 2011-03-03 17:07:50

在XSLT 2.0中,我会这样写:

代码语言:javascript
复制
<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”的硬编码看起来像是一个危险的信号,但只有你才能做出判断。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5173488

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档