RE: [xsl] merging generic elements in a parent-child relationship

Subject: RE: [xsl] merging generic elements in a parent-child relationship
From: "Américo Albuquerque \(E-mail\)" <aalbuquerque@xxxxxxxxxxxxxxxx>
Date: Wed, 26 Jun 2002 16:42:14 +0100
Try this, it worked in IE6

<?xml version="1.0" encoding="ISO-8859-1"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
version="1.0">
 <xsl:output method="xml"/>

 <xsl:key name="idx" match="*" use="@*[starts-with(name(),'id') and (name()
!= 'id')]"/>

 <xsl:template match="root">
  <root>
   <xsl:apply-templates select="*"/>
  </root>
 </xsl:template>

 <xsl:template match="*">
  <xsl:variable name="tag" select="name()"/>
  <xsl:variable name="id" select="@*[starts-with(name(),'id') and (name() !=
'id')]"/>
  <xsl:variable name="ids"
select="../*[@id=$id][concat('id',name())=name($id)]"/>

  <xsl:if test="not(count($ids))">
  <xsl:copy>
   <xsl:copy-of select="@*"/>
   <xsl:apply-templates
select="key('idx',@id)[@*[name()=concat('id',$tag)]]" mode="inside"/>
  </xsl:copy>
  </xsl:if>
 </xsl:template>

 <xsl:template match="*" mode="inside">
  <xsl:variable name="tag" select="name()"/>
  <xsl:copy>
   <xsl:copy-of select="@*"/>
   <xsl:apply-templates
select="key('idx',@id)[@*[name()=concat('id',$tag)]]" mode="inside"/>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>


-----Original Message-----
From: owner-xsl-list@xxxxxxxxxxxxxxxxxxxxxx
[mailto:owner-xsl-list@xxxxxxxxxxxxxxxxxxxxxx]On Behalf Of Matias
Woloski
Sent: Wednesday, June 26, 2002 5:05 AM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: RE: [xsl] merging generic elements in a parent-child
relationship


thanks David,
This works perfect for the test file I've provided. But actually will fail
because I could have something like this

<?xml version="1.0" encoding="UTF-8"?>
<root>
	<a idCountry="1" id="abc" />
	<a idCountry="2" id="abcd" />
	<b id="b1" idPerson="abc"/>
	<b id="b2" idPerson="abc"/>
	<b id="b3" idPerson="abcd"/>
</root>

Note the idCountry attribute which makes the conditions
@*[starts-with(name(.),'id') and (name() != 'id')] to fail.

I will explain a little bit more my problem. This XML is generated through
SQL Server with FOR XML AUTO. So I execute something like
SELECT * FROM Person FOR XML AUTO
SELECT * FROM Email FOR XML AUTO

This could generate something like this.

<?xml version="1.0" encoding="UTF-8"?>
<root>
	<Person idCountry="1" id="1" />
	<Person idCountry="2" id="2" />
	<Email id="1" idPerson="1"/>
	<Email id="2" idPerson="1"/>
	<Email id="3" idPerson="2"/>
</root>

this denotes a relation between Person-Emails. And there could be a lot of
attributes as foreign keys like idCountry which doesn't have relation with
anything inside the xml.

How this can be solved?

Also I have another question. Is there anyway to wrap the Email elements
into another element Emails, like this

<?xml version="1.0" encoding="UTF-8"?>
<root>
	<Person idCountry="1" id="1">
		<Emails>
			<Email id="1" idPerson="1"/>
			<Email id="2" idPerson="1"/>
		</Emails>
	</Person>
	<Person idCountry="2" id="2">
		<Emails>
			<Email id="3" idPerson="2"/>
		</Emails>
	</Person>
</root>

thanks a lot for your help!

Matias

p.s Joerg the xslt you provided doesn't fit my needs because it's specific
to one xml doc and I need to be generic. thanks anyway.

> -----Original Message-----
> From: owner-xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> [mailto:owner-xsl-list@xxxxxxxxxxxxxxxxxxxxxx]On Behalf Of David
> Carlisle
> Sent: martes, 25 de junio de 2002 19:14
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: Re: [xsl] merging generic elements in a parent-child
> relationship
>
>
>
> This may be too generic, it doesn't hard code any element names
> but it doesn't use a parameter to limit them either, if you need to
> paramaterise it you may need to replace * by *[contains($param,name()]
> or some such, but this produces teh specified output on teh test file
>
> David
>
> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
> version="1.0">
> <xsl:output indent="yes"/>
>
> <xsl:key name="idx" match="*" use="@*[starts-with(name(.),'id') and
> (name() != 'id')]"/>
>
> <xsl:template match="root">
> <root>
>  <xsl:apply-templates select="*[not(@*[starts-with(name(.),'id') and
> (name() != 'id')])]"/>
> </root>
> </xsl:template>
> <xsl:template match="*">
> <xsl:copy>
> <xsl:copy-of select="@*"/>
> <xsl:apply-templates select="key('idx',@id)"/>
> </xsl:copy>
> </xsl:template>
>
> </xsl:stylesheet>
>
> _____________________________________________________________________
> This message has been checked for all known viruses by Star Internet
> delivered through the MessageLabs Virus Scanning Service. For further
> information visit http://www.star.net.uk/stats.asp or alternatively call
> Star Internet for details on the Virus Scanning Service.
>
>  XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
>



 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list




 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread