steven.eisenreich
steven.eisenreich

Reputation: 35

XSLT 1.0 get distinct values fails

I need some help with a problem in my xslt code. Used processor/debugger & IDE: MSXML 6.0 in MS Visual Studio 2012.

My exact input (teared down just to the elements i need for my selection.)

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <components>
    <Object3D id="130" plName="STF45668"/>
    <Object3D id="131" plName="RIOD122"/>
    <Object3D id="132" plName="RIOD122"/>
    <Object3D id="133" plName="RIOD122"/>
    <Object3D id="182" plName="RIOD124"/>
    <Object3D id="183" plName="RIOD124"/>
    <Object3D id="184" plName="RIOD124"/>
    <Object3D id="185" plName="RIOD124"/>
  </components>
</root>

My XSLT:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt">
  <xsl:key name ="objectsByName" use="/root/components/Object3D" match="@plName"/>
  <xsl:output media-type="text"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="/">
    <xsl:variable name="allObjs" select="//Object3D"/>
    <xsl:variable name="distinctObjsCount" 
                  select="//Object3D[count(. | key('objectsByName', @plName)[1]) = 1]"/>
    <xsl:variable name="distinctObjsGenID" 
                  select="//Object3D[generate-id() = 
                          generate-id(key('objectsByName', @plName)[1])]"/>

    <xsl:for-each select="//Object3D[count(. | key('objectsByName', @plName)[1]) = 1]">
      <xsl:value-of select="concat(@plName, '(',count(key('objectsByName', @plName)),')')"/>
      <xsl:if test="position() != last()">, </xsl:if>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

This is the transformation output i get:

<?xml version="1.0" encoding="utf-8"?>
STF45668(0), RIOD122(0), RIOD122(0), RIOD122(0), RIOD124(0), RIOD124(0), RIOD124(0), RIOD124(0)

But I fail in getting the distinct values from those Object3D elements.

So... I have no idea why this goes wrong. Does anybody have an idea what I'm doing wrong?

edit: now 1:1 to the files I am using.

Upvotes: 2

Views: 759

Answers (1)

Linga Murthy C S
Linga Murthy C S

Reputation: 5432

Your input doesn't look right to me. A proper input XML would be something like:

<root>
<components>
    <Object3D plName="chair" />
    <Object3D plName="cup" />
    <Object3D plName="desk" />
    <Object3D plName="cup" />
    <Object3D plName="chair" />
    <Object3D plName="chair" />
    <Object3D plName="desk" />
    <Object3D plName="cup" />
</components>
</root>

And, following XSLT should work fine with this XML:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:key name="Object" match="Object3D" use="@plName"/>

<xsl:template match="/root/components">
    <xsl:for-each select="Object3D[count(. | key('Object', @plName)[1]) = 1]">
        <xsl:value-of select="concat(@plName, '(',count(key('Object', @plName)),')')"/>
        <xsl:if test="position() != last()">, </xsl:if>
    </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

The keys are used to group the Object3D, and inside the for-each, forming the output you want:

chair(3), cup(3), desk(2)

Upvotes: 3

Related Questions