Results 1 to 8 of 8

Thread: XSLT: Transforming variable numbers of paragraphs

  1. #1

    Thread Starter
    Junior Member
    Join Date
    May 2004
    Posts
    21

    XSLT: Transforming variable numbers of paragraphs

    Hi folks,

    This will probably sound very very newbie, but I am an XSLT newb...

    Say I have my XML file like so:
    Code:
    <myxml>
        <content>
            <heading>Heading 1</heading>
            <subheading>Heading 2</subheading>
            <paragraph>This is some content. Foo bar, foo bar, foo bar...</paragraph>
            <paragraph>Wooo another paragraph! This is getting repetitive...</paragraph>
            <heading>Another Heading 1</heading>
            <paragraph>YEAH!!!!!!!!!! Oh, right...</paragraph>
        </content>
    </myxml>
    and I have an XSL template something like this....

    Code:
    <xsl:for-each select="heading">
        <h1><xsl:value-of select="heading"></h1>
    </xsl:for-each>
    <xsl:for-each select="subheading">
        <h2><xsl:value-of select="subheading"></h2>
    </xsl:for-each>
    <xsl:for-each select="paragraph">
        <p><xsl:value-of select="paragraph"></p>
    </xsl:for-each>
    Now, I realise that will chuck out 2 <h1> tags followed by one <h2> tag and then my 3 <p> tags.... but how do I get them 'chucked out' in the order in which they appear in the XML file??

    Hope that makes sense... sorry for the poor example.
    I am Remus, come from the dead

  2. #2
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    Create new templates and use apply-templates:
    Code inaccurate, as I'm not that fluent with XSLT.
    Code:
    <xsl:template select="paragraph">
    <p><xsl:apply-templates /></p>
    </xsl:template>
    <xsl:template select="subheading">
    <h2><xsl:apply-templates /></h2>
    </xsl:template>
    <xsl:template select="heading">
    <h1><xsl:apply-templates /></h1>
    </xsl:template>
    
    <xsl:template select="content">
    <xsl:apply-templates />
    </xsl:template>
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  3. #3

    Thread Starter
    Junior Member
    Join Date
    May 2004
    Posts
    21
    Thanks I'll try that out
    I am Remus, come from the dead

  4. #4

    Thread Starter
    Junior Member
    Join Date
    May 2004
    Posts
    21
    Here's what I have:

    example.xml
    Code:
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <myxml>
        <content>
            <heading>Heading 1</heading>
            <subheading>Heading 2</subheading>
            <paragraph>This is some content. Foo bar, foo bar, foo bar...</paragraph>
            <paragraph>Wooo another paragraph! This is getting repetitive...</paragraph>
            <heading>Another Heading 1</heading>
            <paragraph>YEAH!!!!!!!!!! Oh, right...</paragraph>
        </content>
    </myxml>
    example.xsl
    Code:
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <xsl:stylesheet version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
    <xsl:template match="content">
        <div id="content">
            <xsl:apply-templates select="heading" />
    		<xsl:apply-templates select="subheading" />
    		<xsl:apply-templates select="paragraph" />
    	</div>
    </xsl:template>
    
    <xsl:template match="heading">
        <h1><xsl:value-of select="." /></h1>
    </xsl:template>
    
    <xsl:template match="subheading">
        <h2><xsl:value-of select="." /></h2>
    </xsl:template>
    
    <xsl:template match="paragraph">
        <p><xsl:value-of select="." /></p>
    </xsl:template>
    
    <xsl:template match="/">
        <html>
        <body>
    	    <xsl:apply-templates />
        </body>
        </html>
    </xsl:template>
    
    </xsl:stylesheet>
    example.php (transformed using php):
    Heading 1
    Another Heading 1
    Heading 2

    This is some content. Foo bar, foo bar, foo bar...

    Wooo another paragraph! This is getting repetitive...

    YEAH!!!!!!!!!! Oh, right...
    The order therefore of the elements in the output goes h1, h1, h2, p, p, p... when I want it to be in the same order as in the XML file which is: h1, h2, p, p, h1, p

    Any ideas?
    I am Remus, come from the dead

  5. #5
    Frenzied Member axion_sa's Avatar
    Join Date
    Jan 2002
    Location
    Joburg, RSA
    Posts
    1,724
    What is happening is the XSLT processor is locating and applying each template as it hits each apply-template directive. So, after it hits your <apply-templates select="heading" /> it locates and renders each <heading> node before moving to the next line in the template - in your case the <apply-template />. Thus you need to group each individual heading, subheading and paragraph entries into a single entity, and apply that group element before applying the sub-elements

    You need to change your XML to something along the lines of:
    Code:
    <myxml>
        <content>
            <entry>
    	        <heading>Heading 1</heading>
            	<subheading>Heading 2</subheading>
    	        <paragraph>This is some content. Foo bar, foo bar, foo bar...</paragraph>
            	<paragraph>Wooo another paragraph! This is getting repetitive...</paragraph>
            </entry>
            <entry>
                <heading>Another Heading 1</heading>
                <paragraph>YEAH!!!!!!!!!! Oh, right...</paragraph>
    	</entry>
        </content>
    </myxml>
    And your XSLT to include/modify:
    Code:
    <xsl:template match="content">
        <div id="content">
            <xsl:apply-templates select="entry" />
        </div>
    </xsl:template>
    
    <xsl:template match="entry">
        <xsl:apply-templates select="heading" />
        <xsl:apply-templates select="subheading" />
        <xsl:apply-templates select="paragraph" />
    </xsl:template>

  6. #6
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    OR you simply get rid of the select attribute in the apply-templates. You should do that anyway, even if you use axion's structure, which you should, because it structures your data better.
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  7. #7
    Fanatic Member Matt_T_hat's Avatar
    Join Date
    Dec 2001
    Location
    '76 Male Body Evil-Errors: 666
    Posts
    774
    From a logic point of view (I understand only a little XML) the code being submitted works exactly as it should it takes each (thing) as instructed and does something and then it takes each (next thing) and does all of those.

    As per axion_sa to wrap up each set of "Master_Thing" (Thing_Group) you could take each of those and then for each of (things...) do something with in the Master_Thing.

    Otherwise you need to know the exact number of P_things below any given named Heading_Thing and by that time you might as well just publish the original file as HTML and be done as the benifit of templates would be lost.

    What I have just said by talking about collections of things is exactly what axion_sa said except I must have missed that when I hit reply.

    The short answer being that your current XML format does not demonstrate any groupings that would allow you to do waht you want.

    I hope to goodness that this short explination of some of the logic was comprihensable or even usefull. If not ignore me most people do.
    ?
    'What's this bit for anyway?
    For Jono

  8. #8
    Frenzied Member Jop's Avatar
    Join Date
    Mar 2000
    Location
    Amsterdam, the Netherlands
    Posts
    1,986
    I don't know if you got it fixed already, but I think (i'm just starting with xslt) that this is the right way to do it:

    xsl:
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
    	<xsl:template match="/">
    		<html>
    		<body>
    			<xsl:apply-templates />
    		</body>
    		</html>
    	</xsl:template>
    	
    	<xsl:template match="content">
    		<div id="content">
    			<xsl:apply-templates/>
    		</div>
    	</xsl:template>
    	
    	<xsl:template match="heading">
    		<h1><xsl:apply-templates/></h1>
    	</xsl:template>
    	
    	<xsl:template match="subheading">
    		<h2><xsl:apply-templates/></h2>
    	</xsl:template>
    	
    	<xsl:template match="paragraph">
    		<p><xsl:apply-templates/></p>
    	</xsl:template>
    </xsl:stylesheet>
    Jop - validweb.nl

    Alcohol doesn't solve any problems, but then again, neither does milk.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width