Hi Zhimao,
Here's an implementation of Michael Kay's "second approach":
(b) sort the companies in order of price, and take the first
--- compare.xml ---
<compare>
<p>p1</p>
<p>p2</p>
<c>c1.xml</c>
<c>c2.xml</c>
<c>c3.xml</c>
</compare>
Used as input file: you can specify any number of part id's and
any number of 'company'-files.
The stylesheet will collect all the companies into one global variable
with "document(/compare/c)/company", and then for each <p>,
generate a list sorted by price, outputting the first (therefore, it
needs the node-set extension).
--- compare.xsl ---
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl"
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:variable name="companies" select="document(/compare/c)/company"/>
<xsl:template match="/compare">
<result>
<xsl:apply-templates select="p"/>
</result>
</xsl:template>
<xsl:template match="p">
<part>
<id><xsl:value-of select="."/></id>
<xsl:variable name="all">
<xsl:for-each select="$companies/parts/part[id=current()]">
<xsl:sort select="price" data-type="number"/>
<price><xsl:value-of select="price"/></price>
<company><xsl:value-of select="../../name"/></company>
</xsl:for-each>
</xsl:variable>
<xsl:copy-of select="exsl:node-set($all)/price[1]"/>
<xsl:copy-of select="exsl:node-set($all)/company[1]"/>
</part>
</xsl:template>
</xsl:stylesheet>
saxon output.xml compare.xml compare.xsl
--- output.xml ---
<result>
<part>
<id>p1</id>
<price>100</price>
<company>CompanyA</company>
</part>
<part>
<id>p2</id>
<price>100</price>
<company>CompanyC</company>
</part>
</result>
Cheers,
Anton Triest