This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
RE: document() merge DISTINCT
- From: "Chris Bayes" <chris at bayes dot co dot uk>
- To: <xsl-list at lists dot mulberrytech dot com>
- Date: Wed, 19 Dec 2001 16:17:56 -0000
- Subject: RE: [xsl] document() merge DISTINCT
- Reply-to: xsl-list at lists dot mulberrytech dot com
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