springblossom
springblossom

Reputation: 1

Using java String functions in xslt

I am trying to use the java string function with XSLT 1.0. Specifically the the java String replace function.

But it fails with the null pointer exception. Here's what I tried:

1)--Declare namespace and call the java String class 
 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:jString="http://www.oracle.com/XSL/Transform/java/java.lang.String"> 

 2)--Created a template to search for tag inputs that have an ampersand: 
 <xsl:template name="string-replace-all"> 
    <xsl:param name="text" /> 
    <xsl:choose> 
       <xsl:when test="contains($text, '&')"> 
          <xsl:variable name="str1" select="jString:new($text)"/> 
             <xsl:value-of select="jString:replace($str1,'&','&amp;')" /> 
       <xsl:otherwise> 
          <xsl:value-of select="$text" /> 
      </xsl:otherwise> 
    </xsl:choose> 
 </xsl:template> 

 3)--Call the template in the specific tags 
 <Nm> 
    <xsl:variable name="suppNm"> 
       <xsl:call-template name="string-replace-all"> 
          <xsl:with-param name="text" select="Payee/Name" /> 
       </xsl:call-template> 
    </xsl:variable> 
    <xsl:value-of select="$suppNm" /> 
 </Nm> 

However I keep getting a null pointer exception: Caused by: oracle.xdo.parser.v2.XPathException: Extension function error: Error invoking 'replace':'java.lang.NullPointerException'

Can anyone guide me as to how to make this work?

Thanks

Upvotes: 0

Views: 2073

Answers (2)

springblossom
springblossom

Reputation: 1

I found the solution through trial and error. So which the replace for &apos; works well , the same for &amp; does not work. So I used the java String contact function to achieve this:

Here's the final template:

 <xsl:template name="string-replace-all">
        <xsl:param name="text" />
        <xsl:choose>
           <xsl:when test="contains($text, '&amp;') or contains($text, '&amp;') ">
               <xsl:variable name="str1" select="jString:new(translate($text,'áàâäéèêëíìîïóòôöúùûüç','aaaaeeeeiiiioooouuuuc'))"/> 
                <xsl:value-of select="(jString:replaceAll(jString:replaceAll($str1,'&amp;',jString:concat('&amp;','amp;')),'&amp;apos;','&amp;amp;apos;'))" />

               </xsl:when>
           <xsl:otherwise>
              <xsl:value-of select="$text" />
           </xsl:otherwise>
           </xsl:choose>

     </xsl:template>

Upvotes: 0

Alex Fomin
Alex Fomin

Reputation: 505

Analysing your XSL code:

  1. In template string-replace-all there is lack of closed tag when, so add </xsl:when>.
  2. Input XML was not represented, so no one knows what the value inside Payee/Name. Looking at this part contains($text, '&') I suppose Name block has value something like sample1 & sample2. In case of & which is not followed by # (e.g. &#160;), the XML parser is implicitly looking for one of the five predefined entity names lt, gt, amp, quot and apos, or any manually defined entity name. So in input XML the & must be escaped as &amp;.
  3. In case when you use jString:replace(string, target, replacement) NullPointerException exists if target or replacement is null (Java.lang.String.replace() Method), so possibly problem is that target was not picked up cause of &. Also for replacing you can use jString:replaceAll(string, regex, replacement).
  4. Finally example Using java String functions in xslt:

For XML below:

<?xml version="1.0"?>
<Payee>
    <Name>sample1 &amp; sample2</Name>   
</Payee>

Using similar XSL (e.g. replacing &amp; with &quot;):

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:jString="http://www.oracle.com/XSL/Transform/java/java.lang.String" 
                exclude-result-prefixes="jString" version="1.0">
    <xsl:output method="xml"/>

    <xsl:template name="string-replace-all"> 
       <xsl:param name="text" /> 
       <xsl:choose> 
          <xsl:when test="contains($text, '&amp;')"> 
             <xsl:variable name="str1" select="jString:new($text)"/>                 
             <xsl:value-of select="jString:replaceAll($str1, '&amp;','&quot;')" />
          </xsl:when> 
          <xsl:otherwise> 
             <xsl:value-of select="$text" /> 
         </xsl:otherwise> 
       </xsl:choose> 
    </xsl:template> 

    <xsl:template match="/">
        <Nm> 
           <xsl:variable name="suppNm"> 
              <xsl:call-template name="string-replace-all"> 
                  <xsl:with-param name="text" select="/Payee/Name"/> 
              </xsl:call-template> 
           </xsl:variable> 
           <xsl:value-of select="$suppNm" /> 
        </Nm> 
    </xsl:template>   
</xsl:stylesheet>

Result is:

<?xml version="1.0" encoding="UTF-8"?>
<Nm>sample1 " sample2</Nm> 
  1. Mainly important input XML:

    • If you have it simply text with & as below:
    <Payee>
        <Name>Jüërgëns GmbH & S's</Name>
    </Payee>
    

Then you should have error: The entity name must immediately follow the '&' in the entity reference.

  • If you have & in <![CDATA[]]> as below:
<Payee>
    <Name><![CDATA[Jüërgëns GmbH & S's]]></Name>
</Payee>

Then using XSL as below:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml"/>    
    <xsl:template match="/">
        <Nm>
           <xsl:value-of select="/Payee/Name" />
        </Nm> 
    </xsl:template>   
</xsl:stylesheet>

Output will be as below:

<?xml version="1.0" encoding="UTF-8"?>
<Nm>Jüërgëns GmbH &amp; S's</Nm>

Hope all attentions above will help with your case.

Upvotes: 1

Related Questions