如何制作XSLT xsl:如果工作

时间:2013-05-20 18:48:43

标签: xslt xslt-1.0

我正在努力使这个(xml 1.0)代码工作。我是新手,已经筋疲力尽了 尝试不同的方式。有人知道我的错误吗?

<xsl:for-each select="News/Sport">

  <xsl:if test="local-name()='Basketball'">
    <p>
      <xsl:text>Basketball Sport</xsl:text>
    </p>
    <xsl:value-of select="News/Sport/Basketball/Phrases/Phrase"/>
  </xsl:if>

</xsl:for-each>

当我将其转换为HTML文件时,内容不会显示。当我删除xsl:for eachxsl:if statements时,内容已成功展示。我只希望首先检查内容(如果它在XML文件中可用),如果是,那么它是从XML内容中获取的。

提前感谢您的帮助!

编辑:

这是我的XML代码

<News>
  <Sport>
    <Basketball>
      <Phrases>
        <Phrase>Zach Randolph recovered the opening tipoff in Game 1 of the Western Conference Finals, and he didn’t touch the ball again until the possession following the Grizzlies’ first timeout.
        </Phrase>
        <Phrases>
    </Basketball>
  </Sport>
</News>

EDIT2:

你能告诉我为什么我不能在下面的函数中应用模板吗?现在只有文字有效:(

<xsl:for-each select="News/Sport[Basketball]">
  <xsl:apply-templates select="News/Sport/*" />
</xsl:for-each>

  <xsl:template match="Basketball">
    <p>
      <xsl:text>Basketball Sport</xsl:text>
    </p>
    <xsl:apply-templates select="Phrases/Phrase"/>
  </xsl:template>

2 个答案:

答案 0 :(得分:1)

<xsl:for-each select="News/Sport">

    <xsl:if test="local-name()='Basketball'">

在此if测试中,上下文节点是Sport元素,因此local-name()始终为Sport,永远不会与篮球相等。

  

我只希望首先检查内容(如果它在XML文件中可用),如果是,那么它是从XML内容中获取的。

在XSLT中处理此类事情的常用方法是定义与可能存在的各个节点匹配的 templates ,然后将模板应用于实际找到的所有节点。如果没有特定类型的节点,则相应的模板将不会触发

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

  <xsl:template match="/">
    <html>
      <body>
        <!-- apply templates that match all elements inside Sport, which may
             be Basketball, Football, etc. -->
        <xsl:apply-templates select="News/Sport/*" />
      </body>
    </html>
  </xsl:template>

  <!-- when we find a Basketball element ... -->
  <xsl:template match="Basketball">
    <p>
      <xsl:text>Basketball Sport</xsl:text>
    </p>
    <xsl:apply-templates select="Phrases/Phrase"/>
  </xsl:template>

  <!-- when we find a Football element ... -->
  <xsl:template match="Football">
    <p>
      <xsl:text>Football Sport</xsl:text>
    </p>
    <!-- whatever you need to do for Football elements -->
  </xsl:template>

  <xsl:template match="Phrase">
    <p><xsl:value-of select="." /></p>
  </xsl:template>

</xsl:stylesheet>

这样您就不需要任何明确的for-eachif,模板匹配逻辑会为您处理所有这些。

答案 1 :(得分:0)

您错过了上下文节点的想法。在xsl:for-each内,您引用​​的所有内容都与所选节点有关或相对。因此,例如,在<xsl:for-each select="News/Sport">内,上下文节点是Sport元素,像<xsl:if test="local-name()='Basketball'">这样的测试总是 false ,因为本地名称总是Sport

看起来您只需要<xsl:if test="Basketball">来测试当前Basketball节点是否有Sport个子节点。

同样的事情适用于<xsl:value-of select="News/Sport/Basketball/Phrases/Phrase"/>。因为所有内容都与Sport节点相关,所以XSLT在News/Sport/Basketball/Phrases/Phrase元素中寻找Sport ,它永远不会存在。

此外,您可以直接输入文字:此处不需要xsl:text元素,因此您的代码应如下所示

<xsl:for-each select="News/Sport">
  <xsl:if test="Basketball">
    <p>Basketball Sport</p>
    <xsl:value-of select="Basketball/Phrases/Phrase"/>
  </xsl:if>
</xsl:for-each>

您可以通过向for-each选项添加谓词来进一步优化此功能,以便它仅匹配SportBasketball个元素。喜欢这个

<xsl:for-each select="News/Sport[Basketball]">
  <p>Basketball Sport</p>
  <xsl:value-of select="Basketball/Phrases/Phrase"/>
</xsl:for-each>