2010-09-05 27 views
4

J'utilise Xalan 2.7.0 (fourni avec Apache FOP 1.0) et j'ai des problèmes lors de l'utilisation des fonctions de chaîne.Fonctions de chaînes manquant dans Xalan 2.7, java.lang.String utilisé à la place?

La ligne <xsl:value-of select="fn:replace('test', 't', '*')"/> résultats à cette exception:

javax.xml.transform.TransformerException: java.lang.IllegalArgumentException: argument type mismatch 
    at org.apache.fop.cli.InputHandler.transformTo(InputHandler.java:302) 

<xsl:value-of select="fn:string-length('foobar')"/> résultats dans:

javax.xml.transform.TransformerException: java.lang.NoSuchMethodException: For extension function, could not find method java.lang.String.stringLength([ExpressionContext,]). 
    at org.apache.fop.cli.InputHandler.transformTo(InputHandler.java:302) 

Maintenant, c'est bizarre! Pourquoi Xalan recherche-t-il une fonction stringLength au java.lang.String? J'ai testé <xsl:value-of select="fn:substring('foobar', 2, 3)"/>, et en effet: le résultat est o, donc les arguments ont été utilisés comme startIndex, endIndex (comme java.lang.String.substring()) au lieu de foncion XPath fn:substring(string, start, length). Donc je pense que Xalan manque d'une manière ou d'une autre sa bibliothèque de fonctions XPath et utilise la classe String normale à la place. Je l'ai confirmé en appelant la fonction non existante fn:index-of('foobar', 'bar') qui fonctionne bien et mappe à java.lang.String.indexOf(str).

Pourquoi Xalan fait-il cela? Et comment puis-je le réparer? Informations système: Xalan utilise la version Java standard de Mac OS X 10.6.4, 1.6.0_20.

Mise à jour

Bon, laisser de côté la fonction replace() pour un moment. Xalan ne devrait-il pas, étant un processeur XSLT 1.0, implémenter le XPath 1.0 function substring(string, startIndex, length) et non la fonction (string, startIndex, endIndex) que je vois dans mes expirations? Est-ce une coïncidence que cette fonction startIndex, endIndex ressemble à la méthode de sous-chaîne de java.lang.String?

Et pourquoi ai-je une erreur NoSuchMethodError lorsque j'utilise la fonction fn:string-length?

Quelque chose ne va pas ici, et clairement à propos XPath 1.0 n `vs 2.0 ...

+0

Bonne question (1). Voir ma réponse pour l'explication. –

+2

Quel espace de noms utilisez-vous pour le préfixe fn:? Lorsque vous utilisez '' (c'est-à-dire pas de préfixe d'espace de noms sur 'string-length()'), cela donne-t-il encore une exception NoSuchMethodException? – LarsH

+0

LarsH: L'espace de nom est http://www.w3.org/2005/02/xpath-functions, mais comme Alejandro l'écrit ci-dessous, je dois omettre le préfixe fn:. Merci! –

Répondre

3

Le résultat de substring('foobar', 2, 3) (Note: sans espace de noms) doit être oob.

Dans XSLT 1.0, tout appel de fonction avec préfixe sera interprété comme un appel d'extension.De http://www.w3.org/TR/xslt#section-Extension-Functions

Si un FunctionName dans une expression FunctionCall est pas un NCName (à savoir si elle contient un côlon), il est alors traité comme un appel à une fonction d'extension . Le FunctionName est étendu à un nom en utilisant l'espace de noms déclarations du contexte d'évaluation .

7

replace() est une fonction XSLT 2.0. Xalan est un processeur XSLT 1.0.

Vous pouvez simuler le remplacer() avec un template like this from @Ektron Doug D:

<xsl:template name="replace-substring"> 
<xsl:param name="original"/> 
<xsl:param name="substring"/> 
<xsl:param name="replacement" select="''"/> 
<xsl:choose> 
    <xsl:when test="contains($original, $substring)"> 
     <xsl:value-of select="substring-before($original, $substring)"/> 
     <xsl:copy-of select="$replacement"/> 
     <xsl:call-template name="replace-substring"> 
      <xsl:with-param name="original" select="substring-after($original, $substring)"/> 
      <xsl:with-param name="substring" select="$substring"/> 
      <xsl:with-param name="replacement" select="$replacement"/> 
     </xsl:call-template> 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:value-of select="$original"/> 
    </xsl:otherwise> 
</xsl:choose> 
</xsl:template> 

Gardez à l'esprit que cette solution XSLT 1.0 est une trouvaille très simple/remplacer. La fonction XSLT 2.0 replace() peut utiliser des modèles REGEX pour l'expression "find".

+0

Hier soir, j'ai upvoted votre réponse et ce matin il a '0' rep - quelqu'un a downvoted vous et moi :( –

1

Maintenant c'est bizarre! Pourquoi Xalan a-t-il l'air pour une fonction stringLength sur java.lang.String? Je l'ai testé , et en effet: le résultat est o, donc les arguments ont été utilisés comme startIndex, endIndex (comme java.lang.String.substring()) au lieu de fn XPath: substring (chaîne, début, longueur ) foncion.

Je pense donc que Xalan est en quelque sorte manque sa bibliothèque de fonctions XPath et utilisant la classe régulière String à la place. J'ai confirmé cela en appelant la fonction non-existante fn: index-of ('foobar', 'bar') fonctionne bien et mappe à java.lang.String.indexOf (str).

Pourquoi Xalan fait-il cela? Et comment puis-je le réparer?

  1. Pourquoi Xalan faire ça? Parce que Xalan est un processeur XSLT 1.0 et que tout processeur compatible XSLT 1.0 ne prend en charge que XPath 1.0. replace() est une fonction standard de XPath 2.0 et doit être implémentée dans tout processeur XSLT 2.0 compatible.

  2. Et comment puis-je le réparer? En utilisant un processeur XSLT 2.0 comme Saxon 9.x ou AltovaXML2010. Ou écrivez un <xsl:template> récursif et nommé pour faire des remplacements simples dans XSLT 1.0.

4

Quand le vieux Xalan est la seule option, celle-ci fonctionne pour moi:

<xsl:value-of 
    select="java:replaceAll(java:java.lang.String.new(ContactInfo/telephone/text()),'[^0-9]','')"/>