p2p.wrox.com Forums

p2p.wrox.com Forums (http://p2p.wrox.com/index.php)
-   XSLT (http://p2p.wrox.com/forumdisplay.php?f=86)
-   -   Removing duplicate nodes post-process (http://p2p.wrox.com/showthread.php?t=56262)

QuickSilver002 April 4th, 2007 01:35 PM

Removing duplicate nodes post-process
 
(newbie question)
I'm trying to do some post-processing on the results of an XSLT that was made by someone else. My goal is to trim off some duplicate nodes from the results of their transformation. I want my final transform to be a one-step process, so I capture the results of the previous transform in a variable and then I want to modify the nodes in that variable (node-set?).

<xsl:variable name="ORIGINAL_RESULTS">

</xsl:variable>

So, after the above is run, the value of $ORIGINAL_RESULTS is the following:
<XML>
  <A>
    <B>
      <uniqueName>UN1</uniqueName>
    </B>
    <B>
      <uniqueName>UN2</uniqueName>
    </B>
    <B>
      <uniqueName>UN1</uniqueName>
    </B>
  </A>
</XML>

The modification I want to perform is to trim out all the nodes that have duplicate values for their uniqueName children. (i.e. The third <B> node above will be trimmed out) I think the test I want to run is the following:

<xsl:if test="uniqueName">
  <xsl:choose>
    <xsl:when test="uniqueName/text() != preceding-sibling::uniqueName/text()">
      <-- good, output -->
    </xsl:when>
    <xsl:otherwise>
      <-- bad, don't output>
    </xsl:otherwise>
  </xsl:choose>
</xsl:if>

If the node tested has a child named "uniqueName" and the value of that child already exists previously, don't output it.

My problem is that I don't know how to take the variable ORIGINAL_RESULTS and apply the "filter" I've made and have it output the entire XML results except what I've filtered out. Any ideas? (This is probably very simple, I'm new to XSLT though)w how to take the variable ORIGINAL_RESULTS and apply the "filter" I've made and have it output the entire XML results except what I've filtered out. Any ideas? (This is probably very simple, I'm new to XSLT though)


mhkay April 4th, 2007 02:33 PM

>I want my final transform to be a one-step process, so I capture the results of the previous transform in a variable

Actually it's a two-stage process whether the code is all in one stylesheet or in two. Writing a transformation pipeline within a single stylesheet is perhaps operationally more convenient than writing it as multiple stylesheets, but the coding is more awkward because of the need to use multiple modes, it can be harder to debug, it's no faster, and you get fewer opportunities to create reusable or reconfigurable code. Also it can't be done using strict XSLT 1.0 without the node-set() extension.

But if you want to do it, the pattern is

<xsl:variable name="temp">
  <xsl:apply-templates mode="phase1"/>
</xsl:variable>

<xsl:apply-templates select="$temp" mode="phase2"/>

or in XSLT 1.0

<xsl:apply-templates select="xx:node-set($temp)" mode="phase2"/>

where xx:node-set() is an extension function provided in nearly all XSLT 1.0 processors (but in different vendor namespaces).



Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference

mhkay April 4th, 2007 02:37 PM

<xsl:template match="*"> -- * means for all the elements
  <xsl:element name="{local-name()}" namespace="preferred-uri"> -- means element name is always local-name
    <xsl:copy-of select="@*"/> -- means what ?
    <xsl:apply-templates/> -- means what ?
  </xsl:element>
</xsl:template>

If you don't understand this code then you probably ought to take a couple of days off coding and read a good XSLT book (I can recommend one...).

It's a variant on a very commonly used template rule (known as the "identity template") which copies elements unchanged from the input to the output - typically it's supplemented by other template rules that make small changes to specific elements. In this case the xsl:element instruction creates a new element with the same local name as the original but a different namespace URI. The copy-of instruction copies all the attributes unchanged, and the apply-templates call says "process the children" (if you don't know this one then you REALLY should be reading rather than coding!)

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference

QuickSilver002 April 4th, 2007 03:47 PM

Success!

Thanks for your help. I've read some tutorials and have an XSLT book, so I understand most of the terminology. I'm in the unfortunate position of being thrown in the middle of a complex XSLT project with no implementation experience.

Your example template was exactly what I needed. I had seen the identity template in the XSLT spec and knew I needed to use it *somehow* but I just didn't know how.

Thanks again.



All times are GMT -4. The time now is 07:33 AM.

Powered by vBulletin®
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.
© 2013 John Wiley & Sons, Inc.