XSLT编写XPath表达式的正确方法,用于多个条件检查和显示值

时间:2014-02-05 17:12:57

标签: xslt

考虑这个XML,

XML:

<?xml version="1.0" encoding="UTF-8"?>
<items>
    <book>
        <title>doublebell</title>
        <count>available</count>
    </book>
    <phone>
        <brand>nokia</brand>
        <model></model>
    </phone>
</items>
编写XSLT时

映射标准:

  • 仅在输入中存在值时才显示newbook / newtitle。
  • 仅在输入中存在值时显示newbook / newcount。
  • 仅在输入中存在值时才显示newphone / newbrand。
  • 仅在输入中存在值时才显示newphone / newmodel。

XSLT:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" version="1.0" encoding="UTF-8"
        indent="yes" />

    <xsl:variable name="book" select="items/book" />
    <xsl:variable name="phone" select="items/phone" />

    <xsl:template match="/">
        <items>
            <newbook>
                <xsl:if test="$book/title!=''">
                    <newtitle>
                        <xsl:value-of select="$book/title" />
                    </newtitle>
                </xsl:if>
                <xsl:if test="$book/count!=''">
                    <newcount>
                        <xsl:value-of select="$book/count" />
                    </newcount>
                </xsl:if>
            </newbook>
            <xsl:if test="$phone/brand!='' or $phone/model!=''"> <!-- not sure if this condition is required for the above mapping criteria -->
                <newphone>
                    <xsl:if test="$phone/brand!=''">
                        <newbrand>
                            <xsl:value-of select="$phone/brand" />
                        </newbrand>
                    </xsl:if>
                    <xsl:if test="$phone/model!=''">
                        <newmodel>
                            <xsl:value-of select="$phone/model" />
                        </newmodel>
                    </xsl:if>
                </newphone>
            </xsl:if>
        </items>
    </xsl:template>
</xsl:stylesheet>

这是我关注的问题: - 在我的实际XSLT中,我有近70个条件 这个,每次XPath搜索都进行两次[或三次..] 每个条件[例如:<xsl:if test="$phone/brand!=''"><xsl:value-of select="$phone/brand" />以及外if条件。

这是多少性能开销?我在运行申请时感觉不到。

如果这是编写XSLT的正确方法,我想听听有经验的人的意见。我是否需要将路径保存在变量中并重复使用$book$phone?在这种情况下,将有70个+变量来保持这个。

2 个答案:

答案 0 :(得分:1)

使用模板可以完全不同地解决这个问题。如果您定义的模板匹配任何内容为空且不执行任何操作的元素:

<xsl:template match="*[. = '']" />

或者可能使用normalize-space()如果要将元素视为空,只要它们只包含空格

<xsl:template match="*[not(normalize-space())]" />

现在有了这个,为你 感兴趣的元素添加模板

<xsl:template match="book">
  <newbook><xsl:apply-templates /></newbook>
</xsl:template>

<xsl:template match="title">
  <newtitle><xsl:apply-templates /></newtitle>
</xsl:template>

等等。现在,book模板将创建一个newbook元素并继续处理其子元素。当它到达title时,它将有两个不同的模板可供选择,并将选择&#34;最具体的&#34;比赛。如果标题为空,则*[. = '']模板将获胜并且不输出任何内容,仅当标题为非空时才会创建newtitle元素。

通过这种方式,您可以让模板匹配器为您完成大部分工作,您不需要使用xsl:if进行任何明确的条件检查。

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" version="1.0" encoding="UTF-8"
        indent="yes" />

    <xsl:template match="/">
        <items><xsl:apply-templates select="items/*" /></items>
    </xsl:template>

    <!-- ignore empty elements -->
    <xsl:template match="*[not(normalize-space())]" />


    <xsl:template match="book">
      <newbook><xsl:apply-templates /></newbook>
    </xsl:template>

    <xsl:template match="title">
      <newtitle><xsl:apply-templates /></newtitle>
    </xsl:template>
    <!-- and so on with similar templates for the other elements -->

</xsl:stylesheet>

答案 1 :(得分:1)

Ian's answer的基础上,您还可以创建一个通用模板,为您创建“新”元素,而无需单独指定每个元素。这看起来如下所示:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" />

  <xsl:template match="/">
    <items><xsl:apply-templates select="items/*" /></items>
  </xsl:template>

  <xsl:template match="*[not(normalize-space())]" />

  <xsl:template match="*">
    <xsl:element name="{concat('new',name())}">
      <xsl:apply-templates/>
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>

最后一个模板只是通过将单词“new”连接到它的前面来重建元素。