Reputation: 11
I need help with XSLT... In the input xml, I have:
<shop>
<categories>
<category categoryId="63" parentCategoryId="239">
<name>Fruit</name>
</category>
<category categoryId="62" parentCategoryId="239">
<name>Vegetable</name>
</category>
<category categoryId="60" parentCategoryId="221">
<name>Furniture</name>
</category>
...
<categories>
<products>
<product productId="3" productCode="1.05">
<name>Chair</name>
<categories>
<category>60</category>
</categories>
</product>
<product productId="21" productCode="1.59">
<name>Apple</name>
<categories>
<category>63</category>
</categories>
</product>
...
</products>
</shop>
I need to create list of products, where I have name of product and name of its category. How can I do that? This don't work for me...
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:template match="shop">
<export>
<xsl:apply-templates select="products" />
</export>
</xsl:template>
<xsl:template match="products">
<xsl:for-each select="product">
<polozka>
<product_name>
<xsl:value-of select="name" />
</product_name>
<xsl:for-each select="/shop/categories/category">
<xsl:if test="boolean(@categoryId = /shop/products/product/categories/category)">
<category_name>
<xsl:value-of select="name" />
</category_name>
</xsl:if>
</xsl:for-each>
</polozka>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
I'd be glad if there is anybody who can help me...
Upvotes: 1
Views: 311
Reputation: 70618
If you want to look up a category based on its @categoryId then consider using a key to do the looking up
<xsl:key name="category" match="category" use="@categoryId"/>
Then, assuming each Product belongs to only one category, you can simply look up the name of category for a product like so
<xsl:value-of select="key('category', categories/category)/name"/>
Try this XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="category" match="category" use="@categoryId"/>
<xsl:template match="shop">
<export>
<xsl:apply-templates select="products"/>
</export>
</xsl:template>
<xsl:template match="products">
<xsl:for-each select="product">
<polozka>
<product_name>
<xsl:value-of select="name"/>
</product_name>
<category_name>
<xsl:value-of select="key('category', categories/category)/name"/>
</category_name>
</polozka>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
If a Product element could have multiple characters, then you would need to use a for-each loop instead
<xsl:for-each select="categories/category">
<category_name>
<xsl:value-of select="key('category', .)/name"/>
</category_name>
</xsl:for-each>
Upvotes: 1
Reputation: 23637
You are comparing the @CategoryId of each category to all the products:
@categoryId = /shop/products/product/categories/category
which will always be true, since each product is related to an existing category.
You have to compare it to the category of the current product. You don't need a <xsl:if>
for that. It can be done with a predicate. Replace your for-each with this one:
<xsl:for-each select="/shop/categories/category[@categoryId = current()/categories/category]">
<category_name>
<xsl:value-of select="name" />
</category_name>
</xsl:for-each>
Now it should filter out the categories that don't match the categories of the current product.
Upvotes: 0