1

我有一个存储电影及其演员的 XML 文件。

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="index.xsl"?>
<movies
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="movies.xsd">

<movie movieID="1">
    <actors>
        <actor actorID="1"> 
            <name link="hello">Bob</name>
        </actor>

        <actor actorID="2"> 
            <name link="hello">Mike</name> 
        </actor>
    </actors>   
</movie>

<movie movieID="2">
    <actors>
        <actor actorID="1"> 
            <name link="hello">Bob</name>
        </actor>

        <actor actorID="2"> 
            <name>Daniel</name>
        </actor>
    </actors>   
</movie>

</movies>

从上面的代码可以看出,我有 2 个“电影”元素,每个元素包含 2 个“演员”子元素。4 个“name”子元素中有 3 个包含属性“link”:Bob、Mike、Bob

我使用以下 XSLT 代码仅显示包含属性“链接”的参与者的名称:

<xsl:template match="/">
    <xsl:text>Actors: </xsl:text>
    <xsl:apply-templates select="/movies/movie/actors/actor/name[@link]"/>
</xsl:template>

<xsl:template match="name[@link]">
    <xsl:value-of select="." />
    <xsl:element name="br" />
</xsl:template>

我得到的输出:

Bob
Mike
Bob

如您所见,“鲍勃”这个名字重复了两次。我只想显示具有“链接”属性的唯一演员姓名

我尝试了以下 XPath 1.0 查询:

<xsl:template match="[not(@name[@link] = preceding::@name)]">

<xsl:template match="not(@name[@link] = preceding::@name)">

<xsl:template match="not(@name[@link] = preceding-sibling::@name)">

所有这些都使页面显示错误。

4

2 回答 2

2

在 XSLT 1.0 中进行这样的分组的有效方法是使用 Muenchian 分组(为了清楚起见,我添加了 adiv和 a br;请随意删除它们):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
  <xsl:key name="kName" match="actor/name[@link]" use="." />

  <xsl:template match="/">
    <div>
      <xsl:text>Actors: </xsl:text>
      <br />
      <xsl:variable name="actorNames" 
                    select="/movies/movie/actors/actor/name[@link]"/>
      <xsl:apply-templates 
                    select="$actorNames[generate-id() = 
                                        generate-id(key('kName', .)[1])]" />
    </div>
  </xsl:template>

  <xsl:template match="name">
    <xsl:value-of select="." />
    <br />
  </xsl:template>
</xsl:stylesheet>

在您的示例输入上运行时,这会产生:

<div>
  Actors: <br />Bob<br />Mike<br />
</div>
于 2013-03-16T23:05:57.970 回答
-1

XSLT1.0中为小型 XML 源执行此操作的另一种方法:

<xsl:template match="/">
    <xsl:text>Actors: </xsl:text>   
    <xsl:for-each select="/movies/movie/actors/actor/name[@link and not(. = preceding::*)]">
        <xsl:value-of select="."/>
        <br/>
    </xsl:for-each>
</xsl:template>

输出:

Actors: Bob<br/>Mike<br/>
于 2021-08-03T17:45:35.827 回答