|
Subject:
|
XSLT issue to add commas to values
|
|
Posted By:
|
2BOrNot2B
|
Post Date:
|
10/27/2006 2:46:32 PM
|
Hi, I'm using XSLT 2.0 and I have the following problem. This is a subset of the XML.
<Warehouse> <Box> <Color>Blue</Color> <Clothing>Shirt</Clothing> </Box> <Box> <Color>Blue</Color> <Clothing>Pants</Clothing> </Box> <Box> <Color>Brown</Color> <Clothing>Jacket</Clothing> </Box> <Box> <Color></Color> (NOTE: There is no value) <Clothing>Shoes</Clothing> </Box> <Box> <Color>White</Color> <Clothing>Socks</Clothing> </Box> </Warehouse>
I like to create an XSLT that produce the following output (if we could ignore the proper English). "Blue Shirt, Pants Brown Jacket, Shoes White Socks."
So far, I got it to produce the following wrong output. "Blue Shirt, Blue Pants, Brown Jacket, Shoes, White Socks."
Here are my requirements: 1. Put a comma at end of <Clothing> only if the <Color> of next <Clothing> is the same. 2. If <Color> has blank value, then the <Color> is the same as the <Color> of the previous <Clothing>. 3. If <Color> has the same value as previous <Color>, then don't output that <Color> value. 4. End with a period (.).
I appreciate any help on this. I have been twisting my head for the last 3 weeks on this.
|
|
Reply By:
|
mhkay
|
Reply Date:
|
10/27/2006 3:21:51 PM
|
It's always useful with this kind of question if you can show your best attempt, because that makes it possible to see where your misunderstandings of the spec arose.
You've stated the rules very clearly and they translate very directly into XSLT template rules. They don't even need 2.0 facilities, though I've used them where appropriate.
1. Put a comma at end of <Clothing> only if the <Color> of next <Clothing> is the same.
<xsl:template match="Clothing"> <xsl:value-of select="."/> <xsl:if test="../Color = ../following-sibling::Box[1]/Color">,</xsl:if> </xsl:template> 2. If <Color> has blank value, then the <Color> is the same as the <Color> of the previous <Clothing>.
I'm not sure if this rule should be applied before Rule 1, or if it only affects Rule 3. But in 2.0, try
<xsl:function name="f:color" as="xs:string"> <xsl:param name="box" as="xs:element(Box)"/> <xsl:sequence select="if ($box/Color eq '') then $box/preceding-sibling::Box[1]/Color else $box/Color"/> </xsl:function>
and then use f:color(box) in place of box/Color where appropriate
3. If <Color> has the same value as previous <Color>, then don't output that <Color> value.
<xsl:template match="Color"> <xsl:if test="not(f:folor(..) = f:color(../preceding-sibling::Box[1])"> <xsl:value-of select="f:color(..)"/>
4. End with a period (.).
<xsl:template match="Warehouse"> <xsl:apply-templates/> <xsl:text>.</xsl:text> </xsl:template>
Michael Kay http://www.saxonica.com/ Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
|
|
Reply By:
|
2BOrNot2B
|
Reply Date:
|
10/31/2006 10:27:51 AM
|
Appreciate your help, mhkay.
I just got a notice from my boss to write the style sheet in XSLT 1.0 instead of XSLT 2.0. Would you transform your amazing solutions to rules 2 and 3 using XSLT 1.0 instead of XSLT 2.0.
I forgot to mention additional info to Rule 2. "If <Color> has blank value, then the <Color> is the same as the <Color> of the previous <Clothing>. If previous <Color> has a blank value and it is the first <Color>, then that value is default to White."
Example 1: <Warehouse> <Box> <Color></Color> (Note: Default is white) <Clothing>Shirt</Clothing> </Box> <Box> <Color></Color> <Clothing>Pants</Clothing> </Box> <Box> <Color>White</Color> <Clothing>Socks</Clothing> </Box> <Warehouse>
Output of example 1 should be: "White Shirt, Pants, Socks."
Example 2: <Warehouse> <Box> <Color></Color> (Note: Default is white) <Clothing>Shirt</Clothing> </Box> <Box> <Color>Blue</Color> <Clothing>Pants</Clothing> </Box> <Box> <Color></Color> <Clothing>Socks</Clothing> </Box> <Warehouse>
Output of example 2 should be: "White Shirt Blue Pants, Socks."
Again greatly appreciate your help.
|
|
Reply By:
|
mhkay
|
Reply Date:
|
10/31/2006 11:04:57 AM
|
If your boss wants it done the expensive way, how big is her budget?
Actually, it's not that difficult, you just have to use a template rule in a particular mode rather than using a function.
Michael Kay http://www.saxonica.com/ Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
|