This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RE: document() merge DISTINCT


I was testing using non unique ids because I didn't read your request
right.
So I was trying to keep the ids unique within a project. This should
work
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
	<xsl:param name="file" />
	<xsl:variable name="root" select="/" />
	<xsl:template match="/">	
		<p>
		<xsl:apply-templates select="/p/project" />
		<xsl:copy-of select="document($file)/p/project[not(@name
= current()/p/project/@name)]" />
		</p>
	</xsl:template>
	<xsl:template match="project">
		<xsl:copy>
			<xsl:copy-of select="@*" />
			<xsl:copy-of select="*" />
			<xsl:copy-of
select="document($file)/p/project[@name =
current()/@name]/person[not(@id = $root//@id)]" />
		</xsl:copy>
	</xsl:template>
</xsl:stylesheet>

On this input

<?xml version="1.0" ?>
<p>
<project name="some-name1"> 
    <person id="1" name="name1"/>
    <person id="4" name="other-name"/>
    <person id="8" name ="another-name"/>
</project>
<project name="some-name2">
    <person id="2" name="name1"/>
    <person id="5" name="other-name"/>
    <person id="9" name ="another-name"/>
</project>
<project name="some-name3">
    <person id="3" name="name1"/>
    <person id="6" name="other-name"/>
    <person id="10" name ="another-name"/>
    <person id="13" name ="another-name"/>
</project>
</p>

<?xml version="1.0" ?>
<p>
<project name="some-name1"> 
    <person id="1" name="name1"/>
    <person id="4" name="other-name"/>
    <person id="8" name ="another-name"/>
</project>
<project name="some-name2">
    <person id="2" name="name1"/>
    <person id="5" name="other-name"/>
    <person id="9" name ="another-name"/>
</project>
<project name="some-name3">
    <person id="3" name="name1"/>
    <person id="6" name="other-name"/>
    <person id="10" name ="another-name"/>
    <person id="15" name ="another-name"/>
</project>
<project name="some-name4">
    <person id="16" name="name1"/>
    <person id="20" name="other-name"/>
    <person id="24" name ="another-name"/>
    <person id="29" name ="another-name"/>
</project>
</p>	

Gives

<?xml version="1.0" encoding="UTF-16"?>
<p>
<project name="some-name1">
    <person id="1" name="name1" />
    <person id="4" name="other-name" />
    <person id="8" name="another-name" />
</project>
<project name="some-name2">
    <person id="2" name="name1" />
    <person id="5" name="other-name" />
    <person id="9" name="another-name" />
</project>
<project name="some-name3">
    <person id="3" name="name1" />
    <person id="6" name="other-name" />
    <person id="10" name="another-name" />
    <person id="13" name="another-name" />
    <person id="15" name="another-name" />
</project>
<project name="some-name4">
    <person id="16" name="name1" />
    <person id="20" name="other-name" />
    <person id="24" name="another-name" />
    <person id="29" name="another-name" />
</project></p>

If you just want a list of combined unique people then this will do it

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
	<xsl:param name="file" />
	<xsl:template match="/">
		<p>	
		<xsl:copy-of select="//person" />
		<xsl:copy-of select="document($file)//person[not(@id =
current()//@id)]" />
		</p>
	</xsl:template>
</xsl:stylesheet>

The current function just changes context back to the source tree. If
you didn't use it i.e. document($file)//person[not(@id = //@id)] would
give you nothing because the context of //@id would be on the document()
tree. 
This [@id = current()//@id] gives a set of all @ids that are the same
and this [not(@id = current()//@id)] gives a set of all @ids that are
different.

Ciao Chris

XML/XSL Portal
http://www.bayes.co.uk/xml


> -----Original Message-----
> From: owner-xsl-list@lists.mulberrytech.com 
> [mailto:owner-xsl-list@lists.mulberrytech.com] On Behalf Of 
> Alex Schuetz
> Sent: 19 December 2001 12:35
> To: xsl-list@lists.mulberrytech.com
> Subject: Re: [xsl] document() merge DISTINCT
> 
> 
> Hallo Chris,
> 
> it does not work for me as expected..
> 
> I guess, I do not understand the meaning on current() in this context:
> 
> To make it simpler for me, say I have more then two  files I 
> want to merge
> as:
> 
> sample.xml:
> <p>
> <person name="name2" id="2"/>
> <person name="name3" id="8"/>
> <person name="name4" id="32"/>
> </p>
> 
> In each file all /person/@id are unique, but different files 
> might contain the same @id . Now I want to produce a list of 
> all <person> so that /person/@id is unique.
> 
> As you suggested, I tried:
> 
> <xsl:template match="person">
>  <xsl:copy>
>  <xsl:copy-of
>  select="document($file)/p/person[not(@id = current()/p/person/@id]"/>
>   </xsl:copy>
>  </xsl:template>
> 
> It looks to me, that [not(@id = current()/p/person/@id] is 
> always true and I get a list with non unique <person>.
> 
> -Alex
> 
> 
> 
> ----- Original Message -----
> From: "Chris Bayes" <chris@Bayes.co.uk>
> To: <xsl-list@lists.mulberrytech.com>
> Sent: Wednesday, December 19, 2001 12:30 PM
> Subject: RE: [xsl] document() merge DISTINCT
> 
> 
> > Alex,
> > Something like this should do it
> > <?xml version="1.0"?>
> > <xsl:stylesheet version="1.0" 
> > xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
> > <xsl:param name="file" />
> > <xsl:template match="/">
> > <xsl:apply-templates select="/p/project" />
> > <xsl:copy-of select="document($file)/p/project[not(@name
> > = current()/p/project/@name)]" />
> > </xsl:template>
> > <xsl:template match="project">
> > <xsl:copy>
> > <xsl:copy-of select="@*|*" />
> > <xsl:copy-of
> > select="document($file)/p/project[@name = 
> > current()/@name]/person[not(@id = current()/person/@id)]" /> 
> > </xsl:copy> </xsl:template>
> > </xsl:stylesheet>
> >
> > Ciao Chris
> >
> > XML/XSL Portal
> > http://www.bayes.co.uk/xml
> >
> >
> > > -----Original Message-----
> > > From: owner-xsl-list@lists.mulberrytech.com
> > > [mailto:owner-xsl-list@lists.mulberrytech.com] On Behalf Of Alex 
> > > Schuetz
> > > Sent: 19 December 2001 09:31
> > > To: XSL-List@lists.mulberrytech.com
> > > Subject: [xsl] document() merge DISTINCT
> > >
> > >
> > > Hallo;
> > >
> > > I have some input files  with the /person/@id attribute 
> being unique 
> > > in each file (and /project).
> > >
> > > input.xml
> > > --------------------------------------------------------------
> > > <project name="some-name">
> > >     <person id="1" name="name1"/>
> > >     <person id="5" name="other-name"/>
> > >     <preson id="20" name ="another-name"/>
> > > </project>
> > > ------------------------------------------------
> > >
> > > I want to merge these files so that I get a list of all <person> 
> > > that are in any <project> but the preson/@id should be 
> unique, that 
> > > is, no <person> element should be listed twice.
> > >
> > > In the book 'XSLT' from Dough Tidwell (chapter 7) there is an 
> > > example that works but is using a lot of disk reads and deep 
> > > recursion. It goes like this:
> > >
> > > 1: build a variable var1 as a white-space separated 
> sorted list of 
> > > all @id . (using <xsl:for-each select="document(...)"..../> )
> > > 2: build a variable var2 of unique @id from  var1 (by recursion);
> > > 3: with var2 call a template that  calls <xsl:for-each select= 
> > > "document(....)"../> for each id in var2 and produces the output.
> > >
> > > Is there a better way to do this?
> > >
> > > -Alex
> > > asc@ala.de
> > >
> > >
> > >
> > >
> > >  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
> 
> 


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]