Use XSL to remove "outdated" nodes?

J

Jim Bancroft

Hi everyone,

Could someone reccomend a way to remove duplicate/outmoded nodes in an XML
document?

I didn't describe that well, so let me give an example.

For instance, if I have an XML doc like so:

<inventory>
<part>
<name="CPU"/>
<version="4"/>
</part>
<part>
<name="Hard Disk"/>
<version="3"/>
</part>
<part>
<name="CPU"/>
<version="5"/>
</part>
<part>
<name="Keyboard"/>
<version="3"/>
</part>
<part>
<name="Keyboard"/>
<version="3"/>
</part>
</inventory>

I'd like to get a final document with a single CPU element whose
version="5", a Hard Disk element of version="3", and *one* Keyboard element
of version "3". If you could give me a lead, I'd be grateful. Thanks.

-Jim
 
M

Marrow

Hi Jim,

Assuming that your XML were well-formed and looked something like...

<inventory>
<part>
<name>CPU</name>
<version>4</version>
</part>
<part>
<name>Hard Disk</name>
<version>3</version>
</part>
<part>
<name>CPU</name>
<version>5</version>
</part>
<part>
<name>Keyboard</name>
<version>3</version>
</part>
<part>
<name>Keyboard</name>
<version>3</version>
</part>
</inventory>

Then something like (using Muenchian technique to find distinct)...

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:eek:utput method="xml"/>
<!-- key for finding distinct part names -->
<xsl:key name="kDistinctPartName" match="part" use="name"/>
<xsl:template match="inventory">
<inventory>
<xsl:apply-templates select="part[generate-id() =
generate-id(key('kDistinctPartName',name))]"/>
</inventory>
</xsl:template>

<!-- template for handling distinct part names -->
<xsl:template match="part">
<!-- copy only the highest version of this distinct part name -->
<xsl:copy-of select="key('kDistinctPartName',name)[not(version &lt;
key('kDistinctPartName',name)/version)][1]"/>
</xsl:template>
</xsl:stylesheet>


Hope this helps
Marrow
http://www.marrowsoft.com - home of Xselerator (XSLT IDE and debugger)
http://www.topxml.com/Xselerator
 
M

Marrow

Hi Jim,

Assuming that your XML were well-formed and looked something like...

<inventory>
<part>
<name>CPU</name>
<version>4</version>
</part>
<part>
<name>Hard Disk</name>
<version>3</version>
</part>
<part>
<name>CPU</name>
<version>5</version>
</part>
<part>
<name>Keyboard</name>
<version>3</version>
</part>
<part>
<name>Keyboard</name>
<version>3</version>
</part>
</inventory>

Then something like (using Muenchian technique to find distinct)...

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:eek:utput method="xml"/>
<!-- key for finding distinct part names -->
<xsl:key name="kDistinctPartName" match="part" use="name"/>
<xsl:template match="inventory">
<inventory>
<xsl:apply-templates select="part[generate-id() =
generate-id(key('kDistinctPartName',name))]"/>
</inventory>
</xsl:template>

<!-- template for handling distinct part names -->
<xsl:template match="part">
<!-- copy only the highest version of this distinct part name -->
<xsl:copy-of select="key('kDistinctPartName',name)[not(version &lt;
key('kDistinctPartName',name)/version)][1]"/>
</xsl:template>
</xsl:stylesheet>


Hope this helps
Marrow
http://www.marrowsoft.com - home of Xselerator (XSLT IDE and debugger)
http://www.topxml.com/Xselerator
 
J

Jim Bancroft

Dimitre Novatchev said:
This is not well-formed XML.

Sorry, let's try that again-- just something I typed quickly into the news
posting:

<inventory>
<part>
<name>CPU</name>
<version>4</version>
</part>
<part>
<name>Hard Disk</name>
<version>"3"</version>
</part>
<part>
<name>CPU</name>
<version>5</version>
</part>
<part>
<name>Keyboard</name>
<version>"3"</version>
</part>
<part>
<name>Keyboard</name>
<version>3</version>
</part>
</inventory>
 
M

Marrow

Hi Jim,

Assuming that your XML were well-formed and looked something like...

<inventory>
<part>
<name>CPU</name>
<version>4</version>
</part>
<part>
<name>Hard Disk</name>
<version>3</version>
</part>
<part>
<name>CPU</name>
<version>5</version>
</part>
<part>
<name>Keyboard</name>
<version>3</version>
</part>
<part>
<name>Keyboard</name>
<version>3</version>
</part>
</inventory>

Then something like (using Muenchian technique to find distinct)...

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:eek:utput method="xml"/>
<!-- key for finding distinct part names -->
<xsl:key name="kDistinctPartName" match="part" use="name"/>
<xsl:template match="inventory">
<inventory>
<xsl:apply-templates select="part[generate-id() =
generate-id(key('kDistinctPartName',name))]"/>
</inventory>
</xsl:template>

<!-- template for handling distinct part names -->
<xsl:template match="part">
<!-- copy only the highest version of this distinct part name -->
<xsl:copy-of select="key('kDistinctPartName',name)[not(version &lt;
key('kDistinctPartName',name)/version)][1]"/>
</xsl:template>
</xsl:stylesheet>


Hope this helps
Marrow
http://www.marrowsoft.com - home of Xselerator (XSLT IDE and debugger)
http://www.topxml.com/Xselerator
 
D

Dimitre Novatchev

In my solution that uses attributes, just replace in the xsl:sort
instructions:

"@name" with "name"
and
"@version" with "version"



=====
Cheers,

Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top