With XSLT, how can I add a node inside of a for loop? I want to use this if-test with an array, and the element I'd like to search for in the array is returned by a template call inside the for loop...
-
Wednesday, November 21, 2012 12:58 AM
I think this simple example might ask the question a lot more clearly.
I have an input file with multiple products. There are different types of product (2 types with 2 product IDs is fine enough for this example), but the input will have many more.I only want to output the info for the first product of each type that I encounter in the for each Product loop. (I'm outputting info for the lowest priced product, so the first one will be the lowest price because I sort by Rate first.)
So I want to read in each product, but only output the product's info if I haven't already output a product with that same ID. I have a variable for the IDArray, and I want to check if each product inside the for each product loop has an ID that is already in that IDArray - if not, continue, if it is already in the array, skip everything and just loop to the next.
I couldn't figure out how to get the child element to be a node from IDArray with the value of each CurrentID. It keeps adding that value as a node to CurrentID which is only in the scope of each product, not the whole product group. I know the following code does not work, but it illustrates the idea and gives me a place to start:
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" encoding="UTF-8" indent="yes" cdata-section-elements="prod_name adv_notes"/> <xsl:template match="/"> <List> <xsl:for-each select="ProductGroup"> <xsl:sort select="Product/Rate"/> <xsl:variable name="IDarray"> <xsl:for-each select="Product"> <xsl:variable name="CurrentID"> <xsl:call-template name="processID"> <xsl:with-param name="ProductCode" select="ProductCode" /> </xsl:call-template> </xsl:variable> <xsl:if test="not(contains($IDarray, $CurrentID))"> <child elem="{@elem}"> <xsl:select value-of="$CurrentID" /> </child> <Product> <xsl:attribute name="ID"> <xsl:select value-of="$CurrentID" /> </xsl:attribute> <prod_name> <xsl:value-of select="ProductName"/> </prod_name> <rate> <xsl:value-of select="Rate"/> </rate> </Product> </xsl:if> </xsl:for-each> </xsl:variable> </xsl:for-each> </List> </xsl:template> <xsl:template name="processID"> <xsl:param name="ProductCode"/> <xsl:choose> <xsl:when test="starts-with($ProductCode, '515')">5</xsl:when> <xsl:when test="starts-with($ProductCode, '205')">2</xsl:when> </xsl:choose> </xsl:template>
An input would look like this:
<ProductGroup> <Product> <ProductCode> 5155 </ProductCode> <ProductName> House </ProductName> <Rate> 3.99 </Rate> </Product> <Product> <ProductCode> 5158 </ProductCode> <ProductName> House </ProductName> <Rate> 4.99 </Rate> </Product> </ProductGroup> <ProductGroup> <Product> <ProductCode> 2058 </ProductCode> <ProductName> House </ProductName> <Rate> 2.99 </Rate> </Product> <Product> <ProductCode> 2055 </ProductCode> <ProductName> House </ProductName> <Rate> 7.99 </Rate> </Product> </ProductGroup>
Output would be this for only that simple input file:<List> <Product ID=5> <prod_name> House </prod_name> <rate> 3.99 </rate> </Product> <Product ID=2> <prod_name> House </prod_name> <rate> 2.99 </rate> </Product> </List>
Implementing a Muenchian grouping is tough here because my actual dataset is huge. I made it simple to ask a question. If I can just get that array method working, the rest of my huge project will work.
Thanks so much! I know some of the awesome programmers here can help! :)
-Holly
- Moved by Mike FengMicrosoft Contingent Staff, Moderator Friday, November 23, 2012 8:03 AM (From:Common Language Runtime)
All Replies
-
Wednesday, November 21, 2012 6:04 PM
Actually, my problem is a whole lot more complicated, so I tried to make a simple example that I could ask a question with.
The reality is that I'm translating it for another company that has their own IDs I have to assign based on 3 or 4 parameters. So doing a substring won't actually work.
I really needed to figure out the way where I'd add each product ID that I assign to an array so the next time I come across that type, I just skip that loop because that type of product was already done. It just has to be the first one I encounter because I've already sorted it so that the first is the best.
Any idea how to make that node-set method work? I really appreciate the help!
-
Friday, November 23, 2012 8:03 AMModerator
Hi codes,
I moved this thread to a dedicated forum for better support.
Best regards,
Mike Feng
MSDN Community Support | Feedback to us
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
-
Monday, November 26, 2012 5:31 PM
Hi Mike,
Where can I find the place you moved it to, so I can see if anyone answered? :)
Thanks!
-Holly
-
Tuesday, November 27, 2012 2:26 AMModerator
Hi Holly,
Your thread is in the right forum now.
Best regards,
Mike Feng
MSDN Community Support | Feedback to us
Please remember to mark the replies as answers if they help and unmark them if they provide no help.

