devin Posted August 13, 2010 Share Posted August 13, 2010 I am trying to create a template that will remove a child node from a parent and copy everything else as is. Here is some example XML: <item><price><amt>20</amt></price><price><amt>500</amt></price><desc>this is the description</desc><node1>text</node1><node2>text 2</node2><node3 id="1">has id</node3></item> This is what I want to end up with: <item><price><amt>500</amt></price><desc>this is the description</desc><node1>text</node1><node2>text 2</node2><node3 id="1">has id</node3></item> I want to take the highest price, ignore the other price and print out every other node. This is how I am doing it: <xsl:template match="item"> <!-- start of our item --> <item> <xsl:choose> <!-- if we have more then 1 price then we are going to take the biggest one --> <xsl:when test="count(price) > 1"> <!-- get each limit amount --> <xsl:variable name="p1" select="price[1]/amt" /> <xsl:variable name="p2" select="price[2]/amt" /> <!-- find our max --> <xsl:variable name="max"> <xsl:choose> <xsl:when test="$p1 > $p2"> <xsl:value-of select="$p1"/> </xsl:when> <xsl:when test="$p2 > $p1"> <xsl:value-of select="$p2"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$p1"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:apply-templates select="@*|desc|node1|node2|node3" /> <!-- output our price with the max amount --> <price> <amt><xsl:value-of select="$max" /></amt> </price> </xsl:when> <xsl:otherwise> <!-- if we only have 1 price then just print everything out --> <xsl:apply-templates select="@*|node()" /> </xsl:otherwise> </xsl:choose> </item></xsl:template> So to print out all the other nodes I am doing this:<xsl:apply-templates select="@*|desc|node1|node2|node3" />But I don't really like that, I was hoping there was a way to print everything BUT the price. I tried things like this:<xsl:apply-templates select="@*|node()[.!=price] />But that didn't work. Any ideas?Thanks. Link to comment Share on other sites More sharing options...
Martin Honnen Posted August 13, 2010 Share Posted August 13, 2010 If you use XSLT 2.0 (as you can with Saxon 9 http://saxon.sourceforge.net/ or with AltovaXML Tools http://www.altova.com/altovaxml.html) then you could simply write a template that does not copy any price elements not containing the maximun e.g. <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0"> <xsl:strip-space elements="*"/> <xsl:output indent="yes"/> <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@*, node()"/> </xsl:copy> </xsl:template> <xsl:template match="item/price[not(xs:double(amt) eq max(../price))]"/></xsl:stylesheet> Your approach of determing the maximum and then process all child nodes except those price elements not having the maximum looks as follows: <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0"> <xsl:strip-space elements="*"/> <xsl:output indent="yes"/> <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@*, node()"/> </xsl:copy> </xsl:template> <xsl:template match="item"> <xsl:variable name="max-price" as="xs:double" select="max(price/amt)"/> <xsl:copy> <xsl:apply-templates select="@*, node() except price[xs:double(amt) ne $max-price]"/> </xsl:copy> </xsl:template></xsl:stylesheet> Does that help? Or do you need to use XSLT 1.0? Link to comment Share on other sites More sharing options...
boen_robot Posted August 13, 2010 Share Posted August 13, 2010 If you must use XSLT 1.0, you can use the name() function to get the name of a node, and therefore be able to exclude it from the template applying, like: <xsl:apply-templates select="@*|node()[name()!='price'] /> To find out the maximum, I'd reccomend you use the math:max() EXSLT function/template. If you can use the function (as opposed to the template), you can actually reduce the stylesheet to pretty much what the first XSLT 2.0 version looks like. Link to comment Share on other sites More sharing options...
devin Posted August 13, 2010 Author Share Posted August 13, 2010 Thanks for the help guys, that worked great. Really appreciate it. Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.