Jump to content

How to do this?


ohayo85

Recommended Posts

Hi, I'm newbie in XSLT and trying on working in my project. But i have a simple problem which i'm stuck.Suppose i have an XML file like this:...<item> <description1> SOME DATA</description> <description2> SOME DATA</description> <description3>SOME DATA</description></item>...and my XSLT stylesheet would to do this:...<table border="1"> <tr> <td> <xsl:for-each select="/item"> <li><xsl:value-of select="."/></li> </xsl:for-each> </td> </tr></table>...What i trying to achieve is real simple. * <--- consider this start is bullet <li></li>---------------------------------------------------------------------------------------I just want to get an output like this in html:* SOME DATA (description1) * SOME DATA (description2)* SOME DATA (description3)This means i want the <li> to get loop as well cause currently it only give me this output:* SOME DATA (description1) SOME DATA (description2) SOME DATA (description3)I want to make it every description have a bullet and make new line. Although i know can achieve by using <li><xsl:value-of select="description1"/></li><li><xsl:value-of select="description2"/></li><li><xsl:value-of select="description3"/></li>This way will be too specific.But i want to make it looping cause no matter how many description users enter the data into XML file it can display all description.My problem is i don't know how to make the <li> to loop. Perhaps this is simple matter but i'm stuck here. Anyone can help? :)

Link to comment
Share on other sites

If you're the author of that XML, I suggest you use a single name for descriptions and add attributes for extra data like numbers if needed. That way, you can use a single loop for all descriptions, and do specific stuff if needed based on their attributes.If the XML is not under your control, then there are three ways you can achieve this.1. Specifying each element to loop like:

<xsl:for-each select="/item"><ul><xsl:for-each select="description1|description2|description3"><li><xsl:value-of select="."/></li></xsl:for-each></ul></xsl:for-each>

which isn't much better than using three value-of statements.2. Using a universal element selector:

<xsl:for-each select="/item"><ul><xsl:for-each select="*"><li><xsl:value-of select="."/></li></xsl:for-each></ul></xsl:for-each>

which however will also create list items with values for other elements as well, not just descriptions.3. Using a universal element selector with a predicate testing the local-name(), like:

<xsl:for-each select="/item"><ul><xsl:for-each select="*[starts-with(local-name(),'description')]"><li><xsl:value-of select="."/></li></xsl:for-each></ul></xsl:for-each>

Which is practically perfect for the case. If your real XML is in a namespace, you must also add "namespace-uri() = 'THE NAMESPACE URI'" to the predicate.

Link to comment
Share on other sites

Erm. Mr boen_robot, Actually i used your second way to solve my problem. But i'm not really understand on the third way of your implementation. I would like to learn it for future use. :) add "namespace-uri() = 'THE NAMESPACE URI'" to the predicate? Would you mind to give some example based on it?Your feedback will be alot useful to me.Thanks. :)

Link to comment
Share on other sites

Erm. Mr boen_robot, Actually i used your second way to solve my problem. But i'm not really understand on the third way of your implementation. I would like to learn it for future use. :) add "namespace-uri() = 'THE NAMESPACE URI'" to the predicate? Would you mind to give some example based on it?Your feedback will be alot useful to me.Thanks. :)
I was afraid you're going to ask about that.Each XML element has a local name (description1, description2, etc.) but also has a namespace. Namespaces allow you to mix various XML based languages into one document without the parser for one language being confused as to which elements are for it.Look at XSLT for example. Haven't you wondered why all XSLT elements are prefixed with "xsl:" and that you always need to add
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

for the stylesheet to work, "whatever that thing is"That is an XML namespace. Since XSLT is an XML based language that is mixed with another (most often XHTML), the XSLT processor needs a way to distinguish between XHTML and XSLT elements.With the above, you specify that the "xsl" prefix is associated with the URI "http://www.w3.org/1999/XSL/Transform". The URI is XSLT's namespace. An XSLT processor doesn't really care for the prefix, as long as the URI is the same. All elements which have this namespace URI are considered XSLT elements. The part after the prefix is called "local name". An XML namespace can also be made a "default" namespace i.e. applied to all elements without a prefix.So, if your XML had something like

<rootElement xmlns="http://example.com">...<item>...</item>...</rootElement>

in the XSLT, you'd need to write

<xsl:for-each select="*[starts-with(local-name(),'description') and namespace-uri() = 'http://example.com']">

to match only elements that have a local name starting with "description" and a namespace URI of "http://example.com". There's also another way of doing the same thing: declaring your own prefix at the top, associated with this URI like

<xsl:stylesheet version="1.0"xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:my="http://example.com">

and then in the for-each, use that prefix like:

<xsl:for-each select="my:*[starts-with(local-name(),'description')]">

(regardless of what the actual prefix, if any, is in your XML, since again, the prefix is of no importance, as long as it is associated with the same URI)

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...