【问题标题】:Within a XSLT, how do I access one XPath when accessing a different XPath?在 XSLT 中,当访问不同的 XPath 时如何访问一个 XPath?
【发布时间】:2011-11-22 20:22:16
【问题描述】:

提供的示例是我正在尝试做的简化版本。

使用 XSLT,我如何比较来自不同(非子)xpath 中节点的数据?我想将每个cd/artistdvd/director 进行比较,看看它们是否匹配(参见下面的示例)。有多个 cd 和 dvd,但在这个简化的示例中,我只使用了一个。我尝试在一个模板中进行比较,但我无法访问 dvd xpath。而且我无法使用单独的模板访问 dvd xpath。使用单独的模板时,我创建了一个我称之为 (<xsl:call-template name="compare">) 的“比较”模板。通过访问,我的意思是我无法打印出 dvd/director 的值。

我的问题:访问不同的 xpath 时如何访问一个 xpath?我想做的是比较 cd 艺术家和 dvd 导演,看看它们是否匹配。并打印出这些值,如果它们匹配。我想不通的是如何找到艺术家和导演,以便我可以比较他们。我的 xslt 确实打印了 cd 的艺术家值,但我无法打印出 dvd/director 的值。

我的示例如下:

样本来自 W3Schools。我修改了它们以说明我的问题。

XSLT 示例

<xsl:for-each select="catalog/cd">
   <xsl:value-of select="@artist"/>
    <xsl:for-each select="catalog/dvd">         
    <xsl:if test="@director = @artist">
        <xsl:value-of select="@director"/>
    </xsl:if>           
   </xsl:for-each>
 </xsl:for-each>

示例 XML

<?xml version="1.0" encoding="ISO-8859-1"?>
<catalog>   
<cd title="Unchain my heart" artist="Joe Cocker">

    <country>USA</country>
    <company>EMI</company>
    <price>8.20</price>
    <year>1987</year>
</cd>

    <dvd title="My DVD Movie" director="Joe Cocker">
    <country>USA</country>
    <company>WB</company>
    <price>20.00</price>
    <year>1999</year>
    </dvd>
</catalog>

提前感谢您的帮助。

【问题讨论】:

  • 这段代码非常错误:任何地方都没有名为directorartist的属性。

标签: xslt xpath


【解决方案1】:

我认为更大的问题是您在考虑程序方面的问题,而这很少是解决 XSLT 问题的正确方法。更好的方法是先匹配cd 元素,然后选择director 匹配artistdvd 元素。考虑这个样式表:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="/*/cd">
        <xsl:value-of select="artist"/>
        <xsl:apply-templates select="../dvd[director=current()/artist]"
            mode="out"/>
    </xsl:template>
    <xsl:template match="dvd" mode="out">
        <xsl:value-of select="director"/>
    </xsl:template>
    <xsl:template match="dvd"/>
</xsl:stylesheet>

第一个模板将模板应用于所有 dvd 元素,以下谓词对其进行评估:director=current()/artist

当然,就像在您的示例中一样,我们只是将名称 Joe Cocker 打印了两次,这不是很有用。

注意:当有多个cd 元素具有相同的artist 时,这种方法就会失效。更复杂的分组策略可以解决这种情况。

【讨论】:

  • 感谢您的回答。我对示例 XML 进行了编辑,以将艺术家和导演反映为实际属性。我将您的答案应用于我的修复程序,并且有效。我更习惯于 Java 和类似的语言,而 XSLT 对我来说是新的。我还在习惯函数式编程。
【解决方案2】:

做到这一点:

 <xsl:for-each select="/catalog/dvd">   

没有前导斜杠“/”,catalog/dvd是相对于当前节点的, 这是由&lt;xsl:for-each select="catalog/cd"&gt;设置的

【讨论】:

  • 感谢您的回答。感谢您抽出宝贵时间。
【解决方案3】:

您可以简化您的for-each 并使用current()...

<xsl:for-each select="catalog/cd">
  <xsl:value-of select="artist"/>
  <xsl:for-each select="../dvd[director = current()/artist]">
      <xsl:value-of select="director"/>                   
  </xsl:for-each>
</xsl:for-each>

【讨论】:

  • 感谢您的回答。感谢您抽出宝贵时间。
【解决方案4】:

一些指针:

<xsl:for-each select="catalog/cd">

当您这样做时,您就在“内部”每个目录/cd 元素。因此,您的 current() 代表 eacy 目录/cd 元素。

你的“比较函数”:

<xsl:if test="@director = @artist">

不起作用,因为您正在尝试比较属性导演和艺术家。但是没有导演和艺术家的属性,即使有,你也会尝试比较catalog/dvd的属性。

所以 dvd 元素必须类似于 &lt;dvd director="foo" artist="bar"/&gt; 等。

我猜你真正想做的是找到具有相同艺术家/导演的 cd 和 dvd。我不清楚你想要达到什么目的。如果您详细说明,您将得到更好的答案。

【讨论】:

  • 是的,我修正了我的错别字。谢谢你的回答。感谢您抽出宝贵时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-16
  • 2020-12-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多