Reputation: 35
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
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