Note that there are some explanatory texts on larger screens.

plurals
  1. POXSLT filter duplicates in result
    text
    copied!<p>I"m trying to figure out how to avoid duplicates in the result set when applying XSLT transformation (I'm using XSLT 1.0)</p> <p>Here's XML source:</p> <pre><code>&lt;?xml version="1.0" encoding="UTF-8" standalone="yes"?&gt; &lt;?xml-stylesheet type="text/xsl" href="1.xsl"?&gt; &lt;root&gt; &lt;item&gt; &lt;code&gt;AA&lt;/code&gt; &lt;included-code&gt;XX&lt;/included-code&gt; &lt;included-code&gt;YY&lt;/included-code&gt; &lt;included-code&gt;WW&lt;/included-code&gt; &lt;/item&gt; &lt;item&gt; &lt;code&gt;BB&lt;/code&gt; &lt;included-code&gt;ZZ&lt;/included-code&gt; &lt;included-code&gt;XX&lt;/included-code&gt; &lt;included-code&gt;YY&lt;/included-code&gt; &lt;/item&gt; &lt;item&gt; &lt;code&gt;CC&lt;/code&gt; &lt;included-code&gt;VV&lt;/included-code&gt; &lt;included-code&gt;XX&lt;/included-code&gt; &lt;included-code&gt;WW&lt;/included-code&gt; &lt;/item&gt; &lt;/root&gt; </code></pre> <p>Here's stylesheet:</p> <pre><code>&lt;?xml version="1.0"?&gt; &lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt; &lt;xsl:template match="/"&gt; &lt;result&gt; &lt;xsl:apply-templates/&gt; &lt;/result&gt; &lt;/xsl:template&gt; &lt;xsl:template match="item"&gt; &lt;new-item&gt; &lt;code&gt;&lt;xsl:value-of select="code"/&gt;&lt;/code&gt; &lt;xsl:variable name="main_code"&gt;&lt;xsl:value-of select="code"/&gt;&lt;/xsl:variable&gt; &lt;xsl:for-each select="included-code"&gt; &lt;xsl:variable name="current_code"&gt;&lt;xsl:value-of select="text()"/&gt;&lt;/xsl:variable&gt; &lt;included-code&gt;&lt;xsl:value-of select="$current_code"/&gt;&lt;/included-code&gt; &lt;xsl:for-each select="/root/item[included-code=$current_code and code!=$main_code]"&gt; &lt;included-code&gt;&lt;xsl:value-of select="code"/&gt;&lt;/included-code&gt; &lt;/xsl:for-each&gt; &lt;/xsl:for-each&gt; &lt;/new-item&gt; &lt;/xsl:template&gt; &lt;/xsl:stylesheet&gt; </code></pre> <p>Here's the result:</p> <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;result&gt; &lt;new-item&gt; &lt;code&gt;AA&lt;/code&gt; &lt;included-code&gt;XX&lt;/included-code&gt; &lt;included-code&gt;BB&lt;/included-code&gt; &lt;included-code&gt;CC&lt;/included-code&gt; &lt;included-code&gt;YY&lt;/included-code&gt; &lt;included-code&gt;BB&lt;/included-code&gt; &lt;included-code&gt;WW&lt;/included-code&gt; &lt;included-code&gt;CC&lt;/included-code&gt; &lt;/new-item&gt; &lt;new-item&gt; &lt;code&gt;BB&lt;/code&gt; &lt;included-code&gt;ZZ&lt;/included-code&gt; &lt;included-code&gt;XX&lt;/included-code&gt; &lt;included-code&gt;AA&lt;/included-code&gt; &lt;included-code&gt;CC&lt;/included-code&gt; &lt;included-code&gt;YY&lt;/included-code&gt; &lt;included-code&gt;AA&lt;/included-code&gt; &lt;/new-item&gt; &lt;new-item&gt; &lt;code&gt;CC&lt;/code&gt; &lt;included-code&gt;VV&lt;/included-code&gt; &lt;included-code&gt;XX&lt;/included-code&gt; &lt;included-code&gt;AA&lt;/included-code&gt; &lt;included-code&gt;BB&lt;/included-code&gt; &lt;included-code&gt;WW&lt;/included-code&gt; &lt;included-code&gt;AA&lt;/included-code&gt; &lt;/new-item&gt; &lt;/result&gt; </code></pre> <p>The question is - how to avoid with duplicate values in the result. I.e. here's what expected:</p> <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;result&gt; &lt;new-item&gt; &lt;code&gt;AA&lt;/code&gt; &lt;included-code&gt;XX&lt;/included-code&gt; &lt;included-code&gt;BB&lt;/included-code&gt; &lt;included-code&gt;CC&lt;/included-code&gt; &lt;included-code&gt;YY&lt;/included-code&gt; &lt;included-code&gt;WW&lt;/included-code&gt; &lt;/new-item&gt; &lt;new-item&gt; &lt;code&gt;BB&lt;/code&gt; &lt;included-code&gt;ZZ&lt;/included-code&gt; &lt;included-code&gt;XX&lt;/included-code&gt; &lt;included-code&gt;AA&lt;/included-code&gt; &lt;included-code&gt;CC&lt;/included-code&gt; &lt;included-code&gt;YY&lt;/included-code&gt; &lt;/new-item&gt; &lt;new-item&gt; &lt;code&gt;CC&lt;/code&gt; &lt;included-code&gt;VV&lt;/included-code&gt; &lt;included-code&gt;XX&lt;/included-code&gt; &lt;included-code&gt;AA&lt;/included-code&gt; &lt;included-code&gt;BB&lt;/included-code&gt; &lt;included-code&gt;WW&lt;/included-code&gt; &lt;/new-item&gt; &lt;/result&gt; </code></pre> <hr> <p>Thanks LarsH! Looks like the following script does the trick: (I'm relatively new to XSLT, so not sure if there's more elegant way to keep list of already outputted values)</p> <pre><code>&lt;?xml version="1.0"?&gt; &lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt; &lt;xsl:template match="/"&gt; &lt;result&gt; &lt;xsl:apply-templates/&gt; &lt;/result&gt; &lt;/xsl:template&gt; &lt;xsl:template match="item"&gt; &lt;new-item&gt; &lt;code&gt;&lt;xsl:value-of select="code"/&gt;&lt;/code&gt; &lt;xsl:variable name="main_code"&gt;&lt;xsl:value-of select="code"/&gt;&lt;/xsl:variable&gt; &lt;xsl:call-template name="processIncludedCodes"&gt; &lt;xsl:with-param name="main_code" select="./code"/&gt; &lt;xsl:with-param name="codes" select="./included-code"/&gt; &lt;/xsl:call-template&gt; &lt;/new-item&gt; &lt;/xsl:template&gt; &lt;xsl:template name="processIncludedCodes"&gt; &lt;xsl:param name="main_code"/&gt; &lt;xsl:param name="codes"/&gt; &lt;xsl:param name="outputCodes"/&gt; &lt;xsl:if test="$codes"&gt; &lt;xsl:variable name="current_code"&gt;&lt;xsl:value-of select="$codes[1]"/&gt;&lt;/xsl:variable&gt; &lt;xsl:variable name="outputCode" select="concat(':', $codes[1], ':')"/&gt; &lt;xsl:if test="not(contains($outputCodes, $outputCode))"&gt; &lt;included-code&gt;&lt;xsl:value-of select="$codes[1]"/&gt;&lt;/included-code&gt; &lt;/xsl:if&gt; &lt;xsl:for-each select="/root/item[included-code=$current_code and code!=$main_code]"&gt; &lt;xsl:if test="not(contains($outputCodes, ./code))"&gt; &lt;included-code&gt;&lt;xsl:value-of select="code"/&gt;&lt;/included-code&gt; &lt;/xsl:if&gt; &lt;/xsl:for-each&gt; &lt;xsl:variable name="outputCodes2"&gt; &lt;xsl:for-each select="/root/item[included-code=$current_code and code!=$main_code]"&gt; &lt;xsl:value-of select="concat(':', code, ':')"/&gt; &lt;/xsl:for-each&gt; &lt;/xsl:variable&gt; &lt;xsl:variable name="newOutputCodes" select="concat($outputCodes, $outputCode, $outputCodes2)"/&gt; &lt;xsl:call-template name="processIncludedCodes"&gt; &lt;xsl:with-param name="main_code" select="$main_code"/&gt; &lt;xsl:with-param name="codes" select="$codes[position() &gt; 1]"/&gt; &lt;xsl:with-param name="outputCodes" select="$newOutputCodes"/&gt; &lt;/xsl:call-template&gt; &lt;/xsl:if&gt; &lt;/xsl:template&gt; &lt;/xsl:stylesheet&gt; </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload