R Ryff
R Ryff

Reputation: 37

XSLT not compiling in Shell script

This a follow-up from this stackoverflow question - Remove Duplicate Record from XML file using XLST

When using the online XSLT Test Tool (http://xslttest.appspot.com) the solution provided for this question works as expected. However when I implement the xslt into a shell script I receive the following error:

XPath error : Invalid expression
.[generate-id()=generate-id(key('DistinctEAN', @vchEAN)[1])]
 ^
compilation error: file titles_isbn.xsl line 15 element copy-of
xsl:copy-of : could not compile select expression '.[generate-id()=generate-id(key('DistinctEAN', @vchEAN)[1])]'

I do not understand why the xslt works fine when it is used in the XSLT Online Test Tool but not when it is used in a shell script format. Here is my shell script:

#!/bin/sh
echo "Renaissance Duplicate Filter Removal Script Start...."

cd /var/process/renaissance/scripts

xsltproc titles_isbn.xsl /var/process/renaissance/extractedfiles/titles_isbn_test.xml -o /var/process/renaissance/rrin/titles_isbn_nodup.xml

echo "Renaissance Duplicate Filter Removal Script complete"

Here is the titles_isbn.xsl:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="DistinctEAN" match="z:row" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="RowsetSchema" use="@vchEAN" />

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

   <xsl:template match="z:row" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="RowsetSchema" >
   <xsl:copy-of select=".[generate-id()=generate-id(key('DistinctEAN', @vchEAN)[1])]"/>
   </xsl:template>
</xsl:stylesheet>

Any help would be much appreciated.

Upvotes: 0

Views: 537

Answers (2)

Martin Honnen
Martin Honnen

Reputation: 167736

I think XPath 1.0 has a quirk not allowing a predicate after the dot . so use current() instead of the dot.

As an alternative, simply put the negated condition in the match pattern of an empty template:

<xsl:template match="z:row[not(generate-id() = generate-id(key('DistinctEAN', @vchEAN)[1]))]" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="RowsetSchema"/>

Upvotes: 1

Parfait
Parfait

Reputation: 107767

Consider a standard Muenchian Grouping to remove duplicate records, compliant on most XSLT 1.0 processors.

Since I do not know your XML document structure, enter the placeholders for the grouping and matching nodes:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

<xsl:key name="DistinctEAN" match="[ENTERING MATCHING NODE]" use="@vchEAN" />

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

  <xsl:template match="[ENTER GROUPING NODE]">
    <[ENTER GROUPING NODE]>    
    <xsl:for-each select="ENTER MATCHING NODE[generate-id()    
                         = generate-id(key('DistinctEAN', @vchEAN)[1])]">
      <[ENTER MATCHING NODE]>
        <xsl:copy-of select="*"/>
      </[ENTER MATCHING NODE]>
    </xsl:for-each>    
    </[ENTERING GROUPING NODE]>
  </xsl:template>

</xsl:stylesheet>

Upvotes: 1

Related Questions