【问题标题】:XML/XSLT - xsl:key concatXML/XSLT - xsl:key concat
【发布时间】:2014-02-21 18:15:34
【问题描述】:

我有以下 XML 代码:

<training_center>
<course id="XML">
    <title>Course 1</title>
    <keywords>
        <keyword>XML</keyword>
        <keyword>XPath</keyword>
    </keywords>
    <teachers>
        <teacher>Nikitin</teacher>
        <teacher>Pavlov</teacher>
    </teachers>
</course>
<course id="AJAX">
    <title>Course 2</title>
    <keywords>
        <keyword>AJAX</keyword>
        <keyword>XML</keyword>
    </keywords>
    <teachers>
        <teacher>Nikitin</teacher>
        <teacher>Chebykin</teacher>
    </teachers>
</course>
</training_center>

以及下面的XSL代码:

<xsl:key 
    name='concat_key'
    match="/training_center/course"
    use="concat(teachers/teacher, ':', keywords/keyword)"
/>
<xsl:template match="/">                
    <xsl:apply-templates select="key('concat_key', concat('Nikitin',':','XML'))" />
</xsl:template>
<xsl:template match="course">
    <xsl:element name="course">         
        <xsl:value-of select="./title" />
    </xsl:element>
</xsl:template>

XSL 转换之后课程 1 仅显示。但逻辑上课程 2 也应显示。
什么错误?

【问题讨论】:

  • 您使用的是 XSLT 1.0 还是 2.0?

标签: xml xslt concat xslkey


【解决方案1】:

我假设您使用的是 XSLT 1.0,因为 ... [基于您的结果的有根据的猜测]。

首先,您的方法无法工作的原因是concat() 函数适用于string-values,而不是node-sets。

concat(teacher, ':', keyword)

被评估为:

concat(string(teacher), ':', string(keyword))

and(在 XSLT 1.0 中)string(node-set) 返回集合中 first 节点的字符串值。

您可以使用其他方法来实现您的目标,例如:

1.使用带有谓词的键:

<xsl:key name="course-by-teacher" match="course" use="teachers/teacher" />

<xsl:template match="/">
    <output>
        <xsl:apply-templates select="key('course-by-teacher', Nikitin')[keywords/keyword='XML']" />
    </output>
</xsl:template>

<xsl:template match="course">
    <course>         
        <xsl:value-of select="title" />
    </course>
</xsl:template>

2。使用两个键的交集:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:set="http://exslt.org/sets"
extension-element-prefixes="set">
<xsl:output method='xml' version='1.0' encoding='utf-8' indent='yes'/>

<xsl:key name="course-by-teacher" match="course" use="teachers/teacher" />
<xsl:key name="course-by-keyword" match="course" use="keywords/keyword" />

<xsl:template match="/">
    <output>
        <xsl:apply-templates select="set:intersection(key('course-by-teacher', 'Nikitin'), key('course-by-keyword', 'XML'))" />
    </output>
</xsl:template>

<xsl:template match="course">
    <course>         
        <xsl:value-of select="title" />
    </course>
</xsl:template>

</xsl:stylesheet>

请注意,此方法需要 EXSLT set:intersection() 函数,许多 XSLT 1.0 处理器(但不是全部)都支持该函数。如有必要,我将发布一个(更复杂的)方法,该方法可以在 XSLT 1.0 中本地生成两个节点集的交集。

【讨论】:

  • 非常感谢。是的,请发送。在 XSLT 2.0 中我的目标会实现吗?
  • 为什么不从源头阅读它:books.google.com/… 它还讨论了 XSLT 2.0。
【解决方案2】:

concat(teachers/teacher, ':', keywords/keyword) 将为每个 training_center/course 连接第一个老师/老师、':' 和第一个关键字/关键字。但是在您的第二个“课程”中,AJAX 是第一个“关键字”。

【讨论】:

  • 您是否要求选择包含teacher = "Nikitin" 和keyword="XML" 的“课程”?
  • 是的,最好使用concatxsl:key
猜你喜欢
  • 1970-01-01
  • 2023-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-15
  • 2020-07-28
相关资源
最近更新 更多