xsl-list
[Top] [All Lists]

RE: [xsl] Namespace issue when running a Xalan transform through Java

2010-08-31 03:11:06
Martin 

Thanks for the help.  After much angst from Java purists I have got the
project to accept the use of Xalan for the transforms I have to do.

Kind regards
Stephen

-----Original Message-----
From: Martin Honnen [mailto:Martin(_dot_)Honnen(_at_)gmx(_dot_)de] 
Sent: 27 August 2010 18:37
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
Subject: Re: [xsl] Namespace issue when running a Xalan transform
through Java

Etheridge, Stephen wrote:

The extra namespace declarations all appear in elements that are in a
different namespace in the source, but which need to end up in the
namespace www.logica.com/project and are transformed by the following
extract of a stylesheet:

<xsl:template match="*" mode="copy">
                      <xsl:variable name="element-name"
select="local-name()"></xsl:variable>
                      <xsl:choose>
                              <xsl:when test="contains($element-name,
'List')">
                                      <xsl:call-template
name="process-lists"></xsl:call-template>
                              </xsl:when>
                              <xsl:otherwise>
                                      <xsl:element
name="{local-name()}" namespace="http://www.logica.com/project";>
                                      <xsl:apply-templates
mode="copy"></xsl:apply-templates>
                                      </xsl:element>
                              </xsl:otherwise>
                      </xsl:choose>
      
</xsl:template>

      
<xsl:template name="process-lists">   
      <xsl:variable name="element-name"
select="local-name()"></xsl:variable> 
      <xsl:element name="{$element-name}"
namespace="http://www.logica.com/pnd";><xsl:value-of
select="./dip:N"/></xsl:element>      
      <xsl:variable name="local-element-val"><xsl:value-of
select="$element-name"/><xsl:text>LocalVal</xsl:text></xsl:variable>  
      <xsl:element name="{$local-element-val}"
namespace="http://www.logica.com/project";><xsl:value-of
select="./dip:NP"/></xsl:element>             
</xsl:template>

The namespace addition to the <xsl:element> processing is not
reproduced
by XSLTProc or Xalan via the command line, only in the default javax
implementation.

I tried to morph that snippet into a test case, input sample is

<root xmlns="http://example.com/dip";>
   <foo><bar>baz</bar></foo>
   <ListExample>
     <N>N1</N>
     <NP>NP1</NP>
   </ListExample>
   <ListExample>
     <N>N2</N>
     <NP>NP2</NP>
   </ListExample>
   <ListExample>
     <N>N3</N>
     <NP>NP3</NP>
   </ListExample>
</root>

stylesheet is

<xsl:stylesheet
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
   xmlns:dip="http://example.com/dip";
   xmlns="http://www.logica.com/project";
   version="1.0">

   <xsl:template match="/">
     <xsl:apply-templates mode="copy"/>
   </xsl:template>

<xsl:template match="*" mode="copy">
                        <xsl:variable name="element-name"
select="local-name()"></xsl:variable>
                        <xsl:choose>
                                <xsl:when test="contains($element-name,
'List')">
                                        <xsl:call-template
name="process-lists"></xsl:call-template>
                                </xsl:when>
                                <xsl:otherwise>
                                        <xsl:element
name="{local-name()}" >
                                        <xsl:apply-templates
mode="copy"></xsl:apply-templates>
                                        </xsl:element>
                                </xsl:otherwise>
                        </xsl:choose>
        
</xsl:template>

        
<xsl:template name="process-lists">     
        <xsl:variable name="element-name"
select="local-name()"></xsl:variable>   
        <xsl:element name="{$element-name}"
namespace="http://www.logica.com/pnd";><xsl:value-of
select="./dip:N"/></xsl:element>        
        <xsl:variable name="local-element-val"><xsl:value-of
select="$element-name"/><xsl:text>LocalVal</xsl:text></xsl:variable>    
        <xsl:element name="{$local-element-val}"><xsl:value-of
select="./dip:NP"/></xsl:element>               
</xsl:template>

</xsl:stylesheet>

and indeed the output with the Sun/Oracle Java JRE 1.6 transformer is 
both wrong and odd, I get

<?xml version="1.0" encoding="UTF-8"?><root>
   <foo><bar>baz</bar></foo>
   <ns0:ListExample 
xmlns:ns0="http://www.logica.com/pnd";>N1</ns0:ListExample><ListExampleLo
calVal>NP1</ListExampleLocalVal>
   <ns1:ListExample 
xmlns:ns1="http://www.logica.com/pnd";>N2</ns1:ListExample><ListExampleLo
calVal>NP2</ListExampleLocalVal>
   <ns2:ListExample 
xmlns:ns2="http://www.logica.com/pnd";>N3</ns2:ListExample><ListExampleLo
calVal>NP3</ListExampleLocalVal>
</root>

while Saxon 6.5.5 outputs

<?xml version="1.0" encoding="utf-8"?><root 
xmlns="http://www.logica.com/project";>
   <foo><bar>baz</bar></foo>
   <ListExample 
xmlns="http://www.logica.com/pnd";>N1</ListExample><ListExampleLocalVal>N
P1</ListExampleLocalVal>
   <ListExample 
xmlns="http://www.logica.com/pnd";>N2</ListExample><ListExampleLocalVal>N
P2</ListExampleLocalVal>
   <ListExample 
xmlns="http://www.logica.com/pnd";>N3</ListExample><ListExampleLocalVal>N
P3</ListExampleLocalVal>
</root>

So the Sun/Oracle transformer drops one namespace (which is a bug) and 
generates a new prefix for the each element in the other namespace 
(which is awful but probably not a bug considering that the XSLT 1.0 
specification does not outline serialization).


I am not sure what to suggest, it looks as if Michael Dykman was 
completely right. With Java you have two alternative XSLT 1.0 processors

with Xalan and with Saxon 6.5.5 and you can even move to Saxon 9 and 
XSLT 2.0 easily. That seems to be the right approach.

I even tried to avoid the prefix ns[n] clutter with the Sun/Oracle 
transformer by suggesting a prefix in the stylesheet with e.g.

<xsl:stylesheet
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
   xmlns:dip="http://example.com/dip";
   xmlns="http://www.logica.com/project";
   xmlns:pnd="http://www.logica.com/pnd";
   version="1.0">

   <xsl:template match="/">
     <xsl:apply-templates mode="copy"/>
   </xsl:template>

<xsl:template match="*" mode="copy">
                        <xsl:variable name="element-name"
select="local-name()"></xsl:variable>
                        <xsl:choose>
                                <xsl:when test="contains($element-name,
'List')">
                                        <xsl:call-template
name="process-lists"></xsl:call-template>
                                </xsl:when>
                                <xsl:otherwise>
                                        <xsl:element
name="{local-name()}" >
                                        <xsl:apply-templates
mode="copy"></xsl:apply-templates>
                                        </xsl:element>
                                </xsl:otherwise>
                        </xsl:choose>
        
</xsl:template>

        
<xsl:template name="process-lists">     
        <xsl:variable name="element-name"
select="local-name()"></xsl:variable>   
        <xsl:element name="pnd:{$element-name}"><xsl:value-of
select="./dip:N"/></xsl:element>        
        <xsl:variable name="local-element-val"><xsl:value-of
select="$element-name"/><xsl:text>LocalVal</xsl:text></xsl:variable>    
        <xsl:element name="{$local-element-val}"><xsl:value-of
select="./dip:NP"/></xsl:element>               
</xsl:template>

</xsl:stylesheet>

then for instance Saxon honours that and outputs

<?xml version="1.0" encoding="utf-8"?><root 
xmlns="http://www.logica.com/project";>
   <foo><bar>baz</bar></foo>
   <pnd:ListExample 
xmlns:pnd="http://www.logica.com/pnd";>N1</pnd:ListExample><ListExampleLo
calVal>NP1</ListExampleLocalVal>
   <pnd:ListExample 
xmlns:pnd="http://www.logica.com/pnd";>N2</pnd:ListExample><ListExampleLo
calVal>NP2</ListExampleLocalVal>
   <pnd:ListExample 
xmlns:pnd="http://www.logica.com/pnd";>N3</pnd:ListExample><ListExampleLo
calVal>NP3</ListExampleLocalVal>
</root>

but the Sun/Oracle transformer then throws an error "The namespace for 
prefix pnd was not declared" which seems another bug.

-- 

        Martin Honnen
        http://msmvps.com/blogs/martin_honnen/

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--



Please help Logica to respect the environment by not printing this email  / 
Pour contribuer comme Logica au respect de l'environnement, merci de ne pas 
imprimer ce mail /  Bitte drucken Sie diese Nachricht nicht aus und helfen Sie 
so Logica dabei, die Umwelt zu schützen. /  Por favor ajude a Logica a 
respeitar o ambiente nao imprimindo este correio electronico.



This e-mail and any attachment is for authorised use by the intended 
recipient(s) only. It may contain proprietary material, confidential 
information and/or be subject to legal privilege. It should not be copied, 
disclosed to, retained or used by, any other party. If you are not an intended 
recipient then please promptly delete this e-mail and any attachment and all 
copies and inform the sender. Thank you.



--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--