Is this possible in XSLT (logic related)?

Discussion in 'XML' started by Hvid Hat, Feb 7, 2008.

  1. Hvid Hat

    Hvid Hat Guest

    I've got a series of documents in my XML data. The documents have a given
    width. I need to style the documents so the documents with a width of 100
    are in their own line while other documents are grouped two in a line. There
    is always a maximum of 2 columns so it's not possible to have 3 documents
    with a width of 33 in one line.

    So I want my data.xml to results in the following:

    <div class="row">
    <div>DocumentA</div>
    </div>
    <div class="row">
    <div>DocumentB</div>
    <div>DocumentC</div>
    </div>
    <div class="row">
    <div>DocumentD</div>
    <div>DocumentE</div>
    </div>

    - data.xml -

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <?xml-stylesheet type="text/xsl" href="style.xsl"?>
    <documents>
    <document>
    <width>100</width>
    <content>Document A</content>
    </document>
    <document>
    <width>66</width>
    <content>Document B</content>
    </document>
    <document>
    <width>33</width>
    <content>Document C</content>
    </document>
    <document>
    <width>50</width>
    <content>Document D</content>
    </document>
    <document>
    <width>50</width>
    <content>Document E</content>
    </document>
    </documents>

    - style.xsl -

    <?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="document">
    <html>
    <head>
    <title>XSLT</title>
    </head>
    <body>
    <xsl:choose>
    <xsl:when test="width=100">
    <div class="row">
    <div><xsl:value-of select="content"/></div>
    </div>
    </xsl:when>
    <!-- Pseudo begin -->
    <xsl:eek:therwise>
    <div class="row">
    <div><xsl:value-of select="this.content"/></div>
    <div><xsl:value-of select="next.content"/></div>
    next.skip
    </div>
    </xsl:eek:therwise>
    <!-- Pseudo end -->
    </xsl:choose>
    </body>
    </html>
    </xsl:template>
    </xsl:stylesheet
    Hvid Hat, Feb 7, 2008
    #1
    1. Advertising

  2. Hvid Hat wrote:
    >
    > I've got a series of documents in my XML data. The documents have a
    > given width. I need to style the documents so the documents with a width
    > of 100 are in their own line while other documents are grouped two in a
    > line. There is always a maximum of 2 columns so it's not possible to
    > have 3 documents with a width of 33 in one line.
    >



    most grouping problems are easier in xslt 2 tahn xslt 1, but Om assuming
    you want xslt 1 as that's what your example code used.


    <?xml version="1.0" encoding="ISO-8859-1"?>
    <?xml-stylesheet type="text/xsl" href="style.xsl"?>
    <documents>
    <document>
    <width>100</width>
    <content>Document A</content>
    </document>
    <document>
    <width>66</width>
    <content>Document B</content>
    </document>
    <document>
    <width>33</width>
    <content>Document C</content>
    </document>
    <document>
    <width>50</width>
    <content>Document D</content>
    </document>
    <document>
    <width>50</width>
    <content>Document E</content>
    </document>
    </documents>




    <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:strip-space elements="*"/>
    <xsl:eek:utput indent="yes"/>

    <xsl:template match="documents">
    <html>
    <head>
    <title>XSLT</title>
    </head>
    <body>
    <xsl:apply-templates select="document[1]"/>
    </body>
    </html>
    </xsl:template>

    <xsl:template match="document[width=100]">
    <div class="row1">
    <xsl:apply-templates/>
    </div>
    <xsl:apply-templates select="following-sibling::document[1]"/>
    </xsl:template>

    <xsl:template match="document">
    <div class="row">
    <xsl:apply-templates/>
    <xsl:apply-templates
    select="following-sibling::document[1][width!=100]/content"/>
    </div>
    <xsl:apply-templates
    select="(.|following-sibling::document[1][width!=100])[last()]
    /following-sibling::document[1]"/>
    </xsl:template>

    <xsl:template match="width"/>

    <xsl:template match="content">
    <div><xsl:apply-templates/></div>
    </xsl:template>

    </xsl:stylesheet>


    $ saxon data.xml data.xsl
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">

    <title>XSLT</title>
    </head>
    <body>
    <div class="row1">
    <div>Document A</div>
    </div>
    <div class="row">
    <div>Document B</div>
    <div>Document C</div>
    </div>
    <div class="row">
    <div>Document D</div>
    <div>Document E</div>
    </div>
    </body>
    </html>





    --
    http://dpcarlisle.blogspot.com
    David Carlisle, Feb 7, 2008
    #2
    1. Advertising

  3. Hvid Hat

    Hvid Hat Guest

    Hello David,

    > Hvid Hat wrote:
    >
    >> I've got a series of documents in my XML data. The documents have a
    >> given width. I need to style the documents so the documents with a
    >> width of 100 are in their own line while other documents are grouped
    >> two in a line. There is always a maximum of 2 columns so it's not
    >> possible to have 3 documents with a width of 33 in one line.
    >>

    > most grouping problems are easier in xslt 2 tahn xslt 1, but Om
    > assuming you want xslt 1 as that's what your example code used.


    Very nice, David. Thanks! Now, I also want to learn something so could you
    explain the line below?

    <xsl:apply-templates select="(.|following-sibling::document[1][width!=100])[last()]/following-sibling::document[1]"/>

    Apply to the first following sibling with a width different from 100 and
    then what? I'm confused about last(). Is the .| necessary? I tried removing
    it and couldn't see a difference
    Hvid Hat, Feb 8, 2008
    #3
  4. Hvid Hat wrote:
    > Very nice, David. Thanks! Now, I also want to learn something so could
    > you explain the line below?
    >
    > <xsl:apply-templates
    > select="(.|following-sibling::document[1][width!=100])[last()]/following-sibling::document[1]"/>


    As with any programming language, break the expression up and think
    about it in stages.

    (.|following-sibling::document[1][width!=100])

    A list made up of the current node (.) and the first <document> sibling
    after the current node if and only if its width is not 100.

    .... [last()]

    The last node in that list. IE, the following <document> if it met the
    test (width!=100), otherwise the current node.

    .... /following-sibling::document[1]

    The first <document> sibling after the node we just selected. In other
    words, if the next <document> has a width of 100, the one after that;
    otherwise, that next <document>.


    The only complicated thing here is the trick of building a
    one-or-two-node long list and then taking it apart, as a way to say
    "that if found, otherwise this."


    --
    Joe Kesselman / Beware the fury of a patient man. -- John Dryden
    Joseph Kesselman, Feb 8, 2008
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Oleg Konovalov

    XSLT logic

    Oleg Konovalov, May 6, 2005, in forum: XML
    Replies:
    1
    Views:
    482
    Sammy
    May 6, 2005
  2. Maxwell Hammer
    Replies:
    7
    Views:
    638
    Peter Hansen
    Jun 18, 2005
  3. Szymon Janc

    related and unrelated logic

    Szymon Janc, Sep 20, 2007, in forum: VHDL
    Replies:
    2
    Views:
    403
    David Spencer
    Sep 20, 2007
  4. spike
    Replies:
    8
    Views:
    1,459
    Steve Holden
    Feb 9, 2010
  5. Charles R. Thompson

    Question about logic related to a range of numbers

    Charles R. Thompson, Aug 14, 2003, in forum: Perl Misc
    Replies:
    1
    Views:
    84
    Tad McClellan
    Aug 14, 2003
Loading...

Share This Page