Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > XML > Descendent's Relative position neede when flattening XSL

Reply
Thread Tools

Descendent's Relative position neede when flattening XSL

 
 
delgados129
Guest
Posts: n/a
 
      04-24-2005
In a previous post (XSL to Flatten Selective Node in XML:
http://groups-beta.google.com/group/...104948219953e7)
I was skillfully pointed in the right direction with XSL logic to
flatten a selected node.

Given:

<A>
<B/>
<C>
<D>DText1</D>
<D>DText2</D>
<D>
<E>EText1</E>
</D>
<D>DText3</D>
<D>
<E>EText2</E>
</D>
</C>
</A>

Tranforming the XML with the following XSL:

<?xml version="1.0" encoding="UTF-16"?>
<xsl:transform version="1.0"
xmlnssl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xslutput method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="*">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="C">
<xsl:apply-templates mode="flatten">
<xsl:with-param name="currentNode" select="'C'"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="*" mode="flatten">
<xslaram name="currentNode"/>
<xsl:variable name="delimitter" select="'-'" />
<xsl:if test="text()">
<xsl:element name="{$currentNode}{$delimitter}{name()}">
<xsl:value-of select="text()"/>
</xsl:element>
</xsl:if>
<xsl:apply-templates select="*" mode="flatten">
<xsl:with-param name="currentNode"
select="concat($currentNode,$delimitter,name())"/>
</xsl:apply-templates>
</xsl:template>
</xsl:transform>

Will yield:

<A>
<B/>
<C-D>DText1</C-D>
<C-D>DText2</C-D>
<C-D-E>EText1</C-D-E>
<C-D>DText3</C-D>
<C-D-E>EText2</C-D-E>
</A>

Any suggestions on enhancing the transformation to yield the
grandchildren's (great grandchild, great-great grandchild, etc.)
relative element name count. (Note that text 'DText3' within its parent
node is not necessarily an immediate sequential sibling to its logical
sibling.) This is only necessary, as noted in the XSL, for terminating
elements with text. To be more specific, the transform should then
yield:

<A>
<B/>
<C-D-1>DText1</C-D-1>
<C-D-2>DText2</C-D-2>
<C-D-E-1>EText1</C-D-E-1>
<C-D-3>DText3</C-D-3>
<C-D-E-2>EText2</C-D-E-2>
</A>

BTW:

A heartfelt thanks to all that contribute to making this group so
helpful. I enjoy reading through many of the solutions provided here.

 
Reply With Quote
 
 
 
 
David Carlisle
Guest
Posts: n/a
 
      04-25-2005

<xsl:if test="text()">
<xsl:variable name="this" select="name()"/>
<xsl:variable name="n">
<xsl:number level="any" count="*[name()=$this][text()]"/>
</xsl:variable>
<xsl:element name="{$x}_{name()}_{$n}">
<xsl:value-of select="text()"/>
</xsl:element>
</xsl:if>

 
Reply With Quote
 
 
 
 
delgados129
Guest
Posts: n/a
 
      04-25-2005
For documentation completeness, I've incorporated David's logic to
produce the following XSL, also showing its input and final
transformation. Once again, thanks David!

XML Input:

<A>
<B/>
<C>
<D>DText1</D>
<D>DText2</D>
<D>
<E>EText1</E>
</D>
<D>DText3</D>
<D>
<E>EText2</E>
</D>
</C>
</A>



XSL Transform:

<?xml version="1.0" encoding="UTF-16"?>
<xsl:transform version="1.0"
xmlnssl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xslutput method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="*">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>

<!-- Match value is element node to apply flattening logic at -->
<xsl:template match="C">
<xsl:apply-templates mode="flatten">
<xsl:with-param name="currentNode" select="name()"/>
</xsl:apply-templates>
</xsl:template>

<xsl:template match="*" mode="flatten">
<xslaram name="currentNode"/>
<xsl:variable name="delimitter" select="'-'"/>
<xsl:variable name="thisNode" select="name()"/>
<xsl:if test="text()">
<xsl:variable name="descendentNumber">
<xsl:number level="any" count="*[name()=$thisNode][text()]"/>
</xsl:variable>
<xsl:element
name="{$currentNode}{$delimitter}{$thisNode}{$deli mitter}{$descendentNumber}">
<xsl:value-of select="text()"/>
</xsl:element>
</xsl:if>
<xsl:apply-templates select="*" mode="flatten">
<xsl:with-param name="currentNode"
select="concat($currentNode,$delimitter,$thisNode) "/>
</xsl:apply-templates>
</xsl:template>

</xsl:transform>

XML Trasformed to:

<?xml version="1.0" encoding="UTF-8"?>
<A>
<B/>
<C-D-1>DText1</C-D-1>
<C-D-2>DText2</C-D-2>
<C-D-E-1>EText1</C-D-E-1>
<C-D-3>DText3</C-D-3>
<C-D-E-2>EText2</C-D-E-2>
</A>

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Linux sripting help neede Rob S NZ Computing 11 08-02-2007 01:07 AM
Where is Form Relative Position and Absolute Position in VS.Net 2005 ? Luqman ASP .Net 1 02-07-2006 10:27 AM
XSL-FO relative position Caroline XML 2 10-04-2004 03:00 PM
ASP.NET Submit button Double Click issue (non javascript fix neede =?Utf-8?B?UmFqYQ==?= ASP .Net 0 09-16-2004 06:29 PM
neede in australia me_here Digital Photography 1 02-01-2004 01:28 PM



Advertisments