Wrox Programmer Forums
Go Back   Wrox Programmer Forums > XML > XSLT
| Search | Today's Posts | Mark Forums Read
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
  #1 (permalink)  
Old April 28th, 2006, 04:40 AM
Registered User
 
Join Date: Apr 2006
Location: , , .
Posts: 2
Thanks: 0
Thanked 0 Times in 0 Posts
Default flat XML to hierarchical XML

I'm having a problem where I have to translate non hierarchical XML into hierarchical XML, and I can't get my head around to how to do it.

My input looks something like this:
Code:
<test>
 <header>
  <adres>adres 1</adres>
 </header>
 <line>
  <art>art 1a</art>
 </line>
 <line>
  <art>art 1b</art>
 </line>
 <header>
  <adres>adres 2</adres>
 </header>
 <line>
  <art>art 2a</art>
 </line>
 <line>
  <art>art 2b</art>
 </line>
 <line>
  <art>art 2c</art>
 </line>
</test>
and I want to transform this into something like this:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<interchange>
 <message>
  <id>1</id>
  <adres>adres 1</adres>
  <details>
   <art>art 1a</art>
  </details>
  <details>
   <art>art 1b</art>
  </details>
 </message>
 <message>
  <id>2</id>
  <adres>adres 2</adres>
  <details>
   <art>art 2a</art>
  </details>
  <details>
   <art>art 2b</art>
  </details>
  <details>
   <art>art 2c</art>
  </details>
 </message>
</interchange>
My XSLT currently looks like this:
Code:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">
    <interchange>

      <xsl:for-each select="test/header">
        <xsl:variable name="curid" select="position()"/>
      
        <message>
          <id><xsl:value-of select="$curid"/></id>
          <adres><xsl:value-of select="adres"/></adres>
          
          
          <xsl:for-each select="following-sibling::line[ preceding-sibling::header[position() = $curid] ]">
          
            <details>
              <art><xsl:value-of select="art"/></art>
            </details>

          </xsl:for-each>
          
        </message>
      </xsl:for-each>
      
    </interchange>
  </xsl:template>

</xsl:stylesheet>
The for-each which is marked not to work, indeed doesn't work as expected.
The select should basically be something like
"SELECT all following <line> elements who's preceding <header> has the same position as the current <header>" (so basically select all following lines until the next header element).

Could someone please help to write this xpath expression correctly? What am I doing wrong?

Thanks
  #2 (permalink)  
Old April 28th, 2006, 05:43 AM
mhkay's Avatar
Wrox Author
Points: 18,487, Level: 59
Points: 18,487, Level: 59 Points: 18,487, Level: 59 Points: 18,487, Level: 59
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Apr 2004
Location: Reading, Berks, United Kingdom.
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

This problem is often referred to as "positional grouping". In XSLT 2.0 it can be done using <xsl:for-each-group group-starting-with="header">.

In 1.0 it's much trickier: one way is along the lines

for-each select="header"
  for-each select="following-sibling::line[generate-id(preceding-sibling::header[1]) = generate-id(current())]

Other (more efficient) approaches are to reduce it to a value-based grouping problem, using generate-id(preceding-sibling::header[1]) as the grouping key (and then use Muenchian grouping in the usual way), or to to a recursive traversal of the siblings using recursive calls on apply-templates select="following-sibling::*[1]". Try googling for "XSLT positional grouping".

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference


Similar Threads
Thread Thread Starter Forum Replies Last Post
Help in making a FLAT xml to a structured xml shlomi XSLT 0 July 19th, 2007 07:58 AM
tree xml to flat xml whiteadi XSLT 2 November 14th, 2006 02:36 PM
From flat to hierarchical seesharper XSLT 2 February 5th, 2006 06:48 AM
translating a flat xml to a hierarchical xml stevea XSLT 4 June 13th, 2005 05:55 PM
XML non-hierarchical menus rotnative Classic ASP XML 0 June 10th, 2003 02:58 AM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.