tags:

views:

50

answers:

3

first off hello

Ok my question, i am trying to develope a open source shopping cart, which uses xml for storage and xsl to style the basket

1, my xml

<items>
    <item>
        <item-name>vlaue</item-name>
        <item-number>vlaue</item-number>
        <quantity>vlaue<quantity>
        <option>
            <on0>vlaue</on0>
            <os0>vlaue</os0>
            <on1>vlaue</on1>
            <os1>vlaue</os1>
        </option>
    </item>
</items>

This xml would be created for an item with 2 options Since paypal allows a max of 7 options theat is going to be my upper figer ok my xsl

<xsl:for-each select="item">
    <input type='hidden' name="item_name_{position()}" value="{item-name}"/>
    <input type='hidden' name="item_number_{position()}" value="{item-description}"/>
    <input type='hidden' name="amount_{position()}" value="{unit-price}"/>
    <input type='hidden' name="quantity_{position()}" value="{@quantity}"/>
    <xsl:for-each select="option">            
        <input type='hidden' name="on{position()}_(i need this to be item postion)" value="(i need this to be "on" with the option postion appened ie "on0")"/>
        <input type='hidden' name="os{position()}_{i need this to be item postion}" value="(i need this to be "os" with the option postion appened ie "os0")"/>
    </xsl:for-each>
</xsl:for-each>

So really i am asking can i have the value of postion from the outer for each passed to the inner for each

if any one can help it would be graet

Thank you in advance

Tim Dodgson

A: 

Hi Tim,

I'm not 100% sure I completely understand how the XSLT relates to the XML you posted. I think it would make sense to edit your question so you clearly point out:

  • what is the input XML
  • what is the desired output XML
  • what is the XSLT you're struggling with

(I should probably ask this in a comment but currently have to gather enough credits to do so...)

Answering your basic question (abstracting from my confusions): you could always pass such positional information via variables. Just assign the position of the context item in the outer for-each to a variable, and refer to this variable in the inner for-each. As far as I understand your XSLT stylesheet, I assume you're looking for something like this:

<xsl:for-each select="item">
    <xsl:variable name="itemPos" select="position()"/>
    <input type='hidden' name="item_name_{position()}" value="{item-name}"/>
    <input type='hidden' name="item_number_{position()}" value="{item-description}"/>
    <input type='hidden' name="amount_{position()}" value="{unit-price}"/>
    <input type='hidden' name="quantity_{position()}" value="{@quantity}"/>
    <xsl:for-each select="option/*">            
        <input type='hidden' name="{name()}_{$itemPos}" value="{.}"/>
    </xsl:for-each>
</xsl:for-each>

The position of the context item in the outer for-each is stored in a variable $itemPos, which can be referenced further on.

Kind regards,

Ron

rvdb
Thank you for response1, the input xml is what is stated above2, the output is the contents of the basket ready to be sent to paypal3, the xslt i strugling with is how to pass the postion value from the outer for each to the inner for eachthis transfoem is being called on the server from a asp scriptmany thanks for your reply I will see if i can get the variable to workalso on your answer how would i set the value value="(i need this to be "os" or "on" with the option postion appened ie "os0")"
Ok, I edited my answer (as I had forgotten the @value attribute in the innermost <item> elements). Additionally, I think you'd want to start the inner for-each loop for the child elements of <option>. If I understand your desired output correctly, I think my updated code fragment should achieve it.
rvdb
Ron thank you so much, this is so nearly there now, i finally inderstand what you are asking me lol the value needs to equal the contents from the xml name so i if was just hand coding i would write value="{on0}" and value="{os0}" to get the vales from my xml so i need something like value="{on[postion()}" and value="{os[postion()}" so sorry for not being clear in the beginningthank you very much once again for your time and effort
Ahhh, you mean you want this output for those <on>/<os> elements: <input type="hidden" name="on0_1" value="vlaue"/><input type="hidden" name="os0_1" value="vlaue"/><input type="hidden" name="on1_1" value="vlaue"/><input type="hidden" name="os1_1" value="vlaue"/>Then you should change the inner for-each instruction in your XSLT:<xsl:for-each select="option/*[starts-with(name(), 'on')]"> <input type='hidden' name="on{replace(name(), '.*(\d+)', '$1')}_{$itemPos}" value="."/></xsl:for-each>That's why the input XML next to the desired output XML would have been handy.
rvdb
thank you once again, i really do need to buy a good xslt book rather than using google as my book, thanks a gain Tim
A: 

To be honest, I'd reconsider the design of your XML; having the numeric index as part of the tag name is generally not advised, as it makes it much harder to work with in xslt or xsd schemata. I would recommend something along the lines of:

    <option>
        <on index="0">vlaue</on>
        <os index="0">vlaue</os>
        <on index="1">vlaue</on>
        <os index="1">vlaue</os>
    </option>

Then you can simply take the position from the @index attribute, and you can also do <foreach select="os"> to only iterate through all the os elements, for example.

Flynn1179
ok Thank You very much, your effort is great i was thinking of an attribute but did not know if there was an easy xslt answer, u have answered my question i than you again
A: 

Your question is not clear, but I think you need something like this stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
    <xsl:template match="items">
        <form>
            <xsl:apply-templates/>
        </form>
    </xsl:template>
    <xsl:template match="item|option" priority="1">
        <xsl:param name="pos" select="position()"/>
        <xsl:apply-templates select="*">
            <xsl:with-param name="pos" select="$pos"/>
        </xsl:apply-templates>
    </xsl:template>
    <xsl:template match="item/*|option/*">
        <xsl:param name="pos"/>
        <input type='hidden' name="{name()}_{$pos}" value="{.}"/>
    </xsl:template>
</xsl:stylesheet>

With this proper input:

<items>
    <item>
        <item-name>vlaue</item-name>
        <item-number>vlaue</item-number>
        <quantity>vlaue</quantity>
        <option>
            <on0>vlaue</on0>
            <os0>vlaue</os0>
            <on1>vlaue</on1>
            <os1>vlaue</os1>
        </option>
    </item>
</items>

Output:

<form>
    <input type="hidden" name="item-name_1" value="vlaue" />
    <input type="hidden" name="item-number_1" value="vlaue" />
    <input type="hidden" name="quantity_1" value="vlaue" />
    <input type="hidden" name="on0_1" value="vlaue" />
    <input type="hidden" name="os0_1" value="vlaue" />
    <input type="hidden" name="on1_1" value="vlaue" />
    <input type="hidden" name="os1_1" value="vlaue" />
</form>

Note: Pattern matching allows reuse. @priority for resolving item/* and option conflict without rely in error recovery. Adding dummy form for wellformed output (It's not really necesary with a complete stylesheet)

Alejandro