[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Flattening, grouping & ordering elements

Subject: Flattening, grouping & ordering elements
From: "Fjoerie" <Fjoerie@xxxxxxxxxx>
Date: Mon, 26 Apr 2010 12:14:13 +0000
 Flattening
Hi,

Given the following (simplified) input:
<a>
  <b id="b1">
    <c>c1</c>
  </b>
  <b id="b2">
    <c>c2</c>
  </b>
  <b id="b3" special="true">
    <c>c3</c>
  </b>
  <d>d1</d>
  <d>d2</d>
  <e>e1</e>
  <e>e2</e>
  <f id="f1">
    <c>c4</c>
  </f>
  <f id="f2">
    <c>c5</c>
  </f>
  <f id="f3">
    <c>c6</c>
  </f>
  <c>c7</c>
</a>

I need to produce the following output:

x: f1
-----
   c4
-----
   f2
-----
   c5
-----
   f3
-----
   c6
-----
   b1
-----
   c1
-----
   b2
-----
   c2
-----
   b3
-----
   special
-----
   c3
-----
   c7
-----
   e1
-----
   e2
-----
   d1
-----
   d2

Where x is a fixed label that needs to be output on the first line.
Any of the elements could be missing, so x could just as well have to be
output in front of "d1". Outputting the data could be as easy as nesting the
necessary for loops, but the problems I'm facing is how to output the x
without having countless checks to see if elements are missing and how to find
the last line that can't have a border (in reality all of the above is
outputted in a table, where the style of the last line needs to be different,
the label is in a first column & the data in a second column). For example:
the following outputs the elements in the correct order contains no lines. It
will also be hard to maintain if at one point the order of the data should be
output differently due to the if tests to output the label.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
  <xsl:output method="text" encoding="ASCII"/>
  <xsl:template match="/">
    <xsl:apply-templates select="a"/>
  </xsl:template>
  <xsl:template match="a">
    <xsl:if test="count(f) > 0">
      <xsl:text>x: </xsl:text>
    </xsl:if>
    <xsl:for-each select="f">
      <xsl:apply-templates select="."/>
      <xsl:for-each select="c">
        <xsl:apply-templates select="."/>
      </xsl:for-each>
    </xsl:for-each>
    <xsl:if test="(count(f) = 0) and (count(b) > 0)">
      <xsl:text>x: </xsl:text>
    </xsl:if>
    <xsl:for-each select="b">
      <xsl:apply-templates select="."/>
      <xsl:for-each select="c">
        <xsl:apply-templates select="."/>
      </xsl:for-each>
    </xsl:for-each>
    <xsl:if test="(count(f) = 0) and (count(b) = 0) and (count(c) > 0)">
      <xsl:text>x: </xsl:text>
    </xsl:if>
    <xsl:apply-templates select="c"/>
    <xsl:if test="(count(f) = 0) and (count(b) = 0) and (count(c) = 0) and
(count(e) > 0)">
      <xsl:text>x: </xsl:text>
    </xsl:if>
    <xsl:apply-templates select="e"/>
    <xsl:if test="(count(f) = 0) and (count(b) = 0) and (count(c) = 0) and
(count(e) = 0) and (count(d) > 0)">
      <xsl:text>x: </xsl:text>
    </xsl:if>
    <xsl:apply-templates select="d"/>
  </xsl:template>
  <xsl:template match="b|f">
    <xsl:value-of select="@id"/>
    <xsl:text>&#10;</xsl:text>
    <xsl:if test="@special = 'true'">
      <xsl:text>special&#10;</xsl:text>
    </xsl:if>
  </xsl:template>
  <xsl:template match="c|d|e">
    <xsl:value-of select="."/>
    <xsl:text>&#10;</xsl:text>
  </xsl:template>
</xsl:stylesheet>

My second thought was to group everything in one large for-each, in which case
it would be easy to find the first & last line. But then I have no clue on how
to get the order of the elements in the output right:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
  <xsl:output method="text" encoding="ASCII"/>
  <xsl:template match="/">
    <xsl:apply-templates select="a"/>
  </xsl:template>
  <xsl:template match="a">
    <xsl:for-each select="f|f/c|b|b/c|c|e|d">
      <xsl:if test="position() = 1">
        <xsl:text>x: </xsl:text>
      </xsl:if>
      <xsl:apply-templates select="."/>
      <xsl:if test="position() != last()">
        <xsl:text>-----&#10;</xsl:text>
      </xsl:if>
    </xsl:for-each>
  </xsl:template>
  <xsl:template match="b|f">
    <xsl:value-of select="@id"/>
    <xsl:text>&#10;</xsl:text>
    <xsl:if test="@special = 'true'">
      <xsl:text>-----&#10;</xsl:text>
      <xsl:text>special&#10;</xsl:text>
    </xsl:if>
  </xsl:template>
  <xsl:template match="c|d|e">
    <xsl:value-of select="."/>
    <xsl:text>&#10;</xsl:text>
  </xsl:template>
</xsl:stylesheet>

Any suggestions on how to order the set in the second one?

Thanks in advances,

Fjoerie

Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.