Wrox Programmer Forums
Go Back   Wrox Programmer Forums > XML > XSLT
|
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
 
Old June 23rd, 2011, 11:02 AM
Registered User
 
Join Date: Apr 2011
Posts: 8
Thanks: 3
Thanked 0 Times in 0 Posts
Default Problem with grouping

Hi There, hope someone can helps me with the following ; I have a pile of XML content that has been converted from Framemaker files, and I have some inconsistencies with the content. Following is what I have :

<Content>
<StartUnderline/>[<VAR ID="1234" REFID="On"/><StartUnderline/>]<EndUnderline/>: Some blabla 1.
<StartUnderline/>[<VAR ID="5678" REFID="Off"/><StartUnderline/>]<EndUnderline/>: Some blabla2.
</Content>

What I want to get is the following :

<Content>
<u>[<VAR ID="1234" REFID="On"/>]</u>: Some blabla 1.
<u>[<VAR ID="5678" REFID="Off"/>]</u>: Some blabla2.
</Content>

I managed to get things working more or less if every <StartUnderline/> is followed by an <EndUnderline/> later in the tree by using following-sibling:: etc, but the problem is that in some cases there is an obsolete additional <StartUnderline/> in the node (as shown in example).

So, what I tried to do is write something like 'encapsulate all tags in a <u> tag from the first <StartUnderline/> tag onward, and ignore all following <StartUnderline/> tags until you get an <EndUnderline/> tag.Then close the <u> tag.

Or to simplify something like this :

<some tags...>
<some tags...>
<StartUnderline/> <-- Replace with <u>
<some tags...>
<some tags...>
<StartUnderline/> <-- IGNORE / KICK OUT !!!
<some tags...>
<some tags...>
<EndUnderline/><! -- Replace with </u>
<some tags...>
<some tags...>

... but it's a bit above my head, so any advice would be highly appreciated
 
Old June 23rd, 2011, 11:30 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

If you can trust the end-underline elements, try something like:

Code:
<xsl:for-each-group select="node()" group-ending-with="end-underline">
  <xsl:variable name="start" select="current-group()[self::start-underline][1]"/>
  <xsl:copy-of select="current-group()[$start >> .]"/>
  <u>
     <xsl:copy-of select="current-group()[. >> $start][not(self::start-underline)][not(self::end-underline)]"/>
  </u>
</xsl:for-each-group>
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
 
Old June 23rd, 2011, 04:12 PM
Registered User
 
Join Date: Apr 2011
Posts: 8
Thanks: 3
Thanked 0 Times in 0 Posts
Default Right direction, still got lost

Thanks already for this tip, but I'm not able to get it running. I've been checking the web for some examples on using grouping (I'm fairly new to xslt 2.0 to be honnest), but all examples expect nice, clean structured input. not real live data...

What I tried is the following : make a simple xml file containing some examples of the various ways the underline tags are provided.

xml sample :

<TestFile>
<!-- Para tag containing no underline tags -->
<Para>
<Content>[text_not_underlined]</Content>
</Para>
<!-- correct encapsulation from source -->
<Para>
<Content>
<Underline/>[text_to_be_underlined]<EndUnderline/>
<p>Some test data</p>
</Content>
</Para>
<!-- extra underline tag that should be ignored -->
<Para>
<Content>
<Underline/>[text_to_be_underlined]<Underline/>
<EndUnderline/>
<p>Some other test data</p>
</Content>
</Para>
<!-- some extra end underline tags that should be ignored -->
<Para>
<Content>
<EndUnderline/>[no_longer_underline]<EndUnderline/>
<p>: More data</p>
</Content>
</Para>
</TestFile>

When using your group coding in a template results are not exactly what I expected, so I'm probably overlooking something. I.ve tried various things, but neither one of these were successful. Could you therefore look at below, and point me to what I do wrong ? I manage indeed to encapsulate my underlined content in a u tag, but the rest of the content is gone

-----------------------
Stylesheet
-----------------------

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Content">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:for-each-group select="node()" group-ending-with="EndUnderline">
<xsl:variable name="start" select="current-group()[self::Underline][1]"/>
<xsl:copy-of select="current-group()[$start >> .]"/>
<u>
<xsl:copy-of select="current-group()[. >> $start][not(self::Underline)][not(self::EndUnderline)]"/>
</u>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>


-----------------------
Current result
-----------------------

<TestFile>
<!-- Para tag containing no underline tags -->
<Para>
<Content>
<u/>
</Content>
</Para>
<!-- correct encapsulation from source -->
<Para>
<Content>
<u>[text_to_be_underlined]</u>
<u/>
</Content>
</Para>
<!-- extra underline tag that should be ignored -->
<Para>
<Content>
<u>[text_to_be_underlined]</u>
<u/>
</Content>
</Para>
<!-- some extra end underline tags that should be ignored -->
<Para>
<Content>
<u/>
<u/>
</Content>
</Para>
</TestFile>

-----------------------
Hoped for result
-----------------------

<TestFile>
<!-- Para tag containing no underline tags -->
<Para>
<Content>[text_not_underlined]</Content>
</Para>
<!-- correct encapsulation from source -->
<Para>
<Content>
<u>[text_to_be_underlined]</u>
<p>Some test data</p>
</Content>
</Para>
<!-- extra underline tag that should be ignored -->
<Para>
<Content>
<u>[text_to_be_underlined]</u>
<p>Some other test data</p>
</Content>
</Para>
<!-- some extra end underline tags that should be ignored -->
<Para>
<Content>
[no_longer_underline]
<p>: More data</p>
</Content>
</Para>
</TestFile>


Since the actual XML file is pretty large and containing a lot more data and variety of tags, I assume some way of working with the identity template needs to be done, but I can't figure out how to make it work together with the group template. If it might make things easier ; all content to be underlined resides within a <Content> tag, but lot more additional tags as shown in the example can be underneeth the <Content> tag.


Thanks again for any support on this !

Last edited by wokoman; June 24th, 2011 at 03:11 AM..
 
Old June 24th, 2011, 05:00 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

The reason content disappears when there is no underline tag is that this

Code:
<xsl:variable name="start" select="current-group()[self::Underline][1]"/>
 <xsl:copy-of select="current-group()[$start >> .]"/>
produces no output when $start is empty. So try changing it to

Code:
<xsl:variable name="start" select="current-group()[self::Underline][1]"/>
 <xsl:copy-of select="current-group()[empty($start) or ($start >> .)]"/>
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
The Following User Says Thank You to mhkay For This Useful Post:
wokoman (June 24th, 2011)
 
Old June 24th, 2011, 06:21 AM
Registered User
 
Join Date: Apr 2011
Posts: 8
Thanks: 3
Thanked 0 Times in 0 Posts
Default Thanks a million !

Thanks mhkay, I had to alter it a bit since I still ended up with some empty <u/> tags but you placed me in the right track. I used the start variable itself to make the choice, if available > copy the group, if not > treat data as 'normal'.

This is what I finally came up with, and it works like a charm so I hope it can be usefull for others too :

Code:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>

<xsl:template match="/">
<xsl:copy>
	<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>

<xsl:template match="@*|node()">
<xsl:copy>
	<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>

<xsl:template match="Content">
<xsl:copy>
	<xsl:for-each-group select="node()" group-ending-with="EndUnderline">
	<xsl:variable name="start" select="current-group()[self::Underline][1]"/>

	<xsl:choose>

<!-- if there is a match group the data and copy it -->

	<xsl:when test="$start">
	<xsl:copy-of select="current-group()[$start >> .]"/>
	<u>
	<xsl:copy-of select="current-group()[. >> $start][not(self::Underline)][not(self::EndUnderline)]"/>
	</u>
	</xsl:when>

<!-- Otherwise apply templates to selected content -->

	<xsl:otherwise>
	<xsl:apply-templates select="current-group()"/>
	</xsl:otherwise>
	</xsl:choose>
	</xsl:for-each-group>
</xsl:copy>
</xsl:template>

<!-- Now get rid of stand alone EndUnderline tags -->

<xsl:template match="EndUnderline"/>

</xsl:stylesheet>





Similar Threads
Thread Thread Starter Forum Replies Last Post
Totals Grouping Problem pallone XSLT 12 June 15th, 2010 01:41 PM
Grouping problem [email protected] XSLT 3 July 27th, 2009 06:19 AM
Problem of grouping in XSLT LeoMathew XSLT 2 September 11th, 2008 09:38 AM
Grouping problem bonekrusher XSLT 3 April 7th, 2007 05:11 PM
Grouping problem aware Access 11 August 4th, 2005 11:00 AM





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