1
votes

i have two xml files:

products.xml

<lists>
<list id="0">
      <group id="53149">
        <product id="87563223"/>
        <product id="25000016"/>
      </group>
      <group id="138939">
        <product id="2400004"/>
        <product id="2400005"/>
      </group>
</list>
<list id="1">
      <group id="34181">
        <product id="2249213"/>
      </group>
      <group id="73892">
        <product id="1306005"/>
        <product id="9300001"/>
      </group>
</list>
</lists>

and valid_products.xml

<ValidProducts>
  <product>
     <ID>1306005</ID>
  </product>
  <product>
     <ID>87563223</ID>
  </product>
</ValidProducts>

I'am using xslt with Saxon-HE processor for removing from the first file products, wich ids do not match provided ids in the second file

The result xml :

<lists>
<list id="0">
      <group id="53149">
        <product id="87563223"/>
      </group>
      <group id="138939">
      </group>
</list>
<list id="1">
      <group id="34181">
      </group>
      <group id="73892">
        <product id="1306005"/>
      </group>
</list>
</lists>

Here's my xsl:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xhtml="http://www.w3.org/1999/xhtml" version="2.0">     
    <xsl:output indent="no"/>
    <xsl:strip-space elements="*"/>
    <xsl:param name="f1" />
    <xsl:variable name="doc1" select="document($f1)"/>

    <xsl:variable name="valids" select="$doc1/ValidProducts/product/ID/text()" />

    <xsl:template match="@* | node()"> 
        <xsl:copy> 
            <xsl:apply-templates select="@* | node()"/> 
        </xsl:copy> 
    </xsl:template>  
    <xsl:template match="/lists/list//product[@id[not(. = $valids)]]"/>
</xsl:stylesheet>

I pass the second file to the xsl stylesheet as a parameter, it works fine, but for big files (more than 200mb) it's really slow, how can i optimize it?

1

1 Answers

0
votes

Use a key:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xhtml="http://www.w3.org/1999/xhtml" version="2.0">     
    <xsl:output indent="no"/>
    <xsl:strip-space elements="*"/>
    <xsl:param name="f1" />
    <xsl:variable name="doc1" select="document($f1)"/>

    <xsl:key name="by-id" match="ValidProducts/product" use="ID"/>


    <xsl:template match="@* | node()"> 
        <xsl:copy> 
            <xsl:apply-templates select="@* | node()"/> 
        </xsl:copy> 
    </xsl:template>  

    <xsl:template match="/lists/list//product[not(key('by-id', @id, $doc1))]"/>
</xsl:stylesheet>