Select unique element values based on the attribute with XPath 1.0

佐手、 提交于 2019-12-23 03:29:11

问题


I have an XML file that stores movies and their actors.

<?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>

As you can see from the code above, I have 2 "movie" elements that contain 2 "actor" child elements each. 3 out of 4 "name" child elements contain an attribute "link": Bob, Mike, Bob

I'm using the following XSLT code to display only the names of the actors that contain an attribute "link":

<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>

The output that I get:

Bob
Mike
Bob

As you can see the name "Bob" repeats twice. I want to display only unique actor names that have an attribute "link"

I have tried the following XPath 1.0 queries:

<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)">

All of them made the page display an error.


回答1:


The efficient way to do grouping like this in XSLT 1.0 is to use Muenchian grouping (I've added a div and a br for clarity; feel free to remove them):

<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>

When run on your sample input, this produces:

<div>
  Actors: <br />Bob<br />Mike<br />
</div>


来源:https://stackoverflow.com/questions/15455618/select-unique-element-values-based-on-the-attribute-with-xpath-1-0

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!