RE: [xsl] RE: unwanted and non prefix namespaces in output

Subject: RE: [xsl] RE: unwanted and non prefix namespaces in output
From: "Michael Kay" <mhk@xxxxxxxxx>
Date: Sun, 1 Aug 2004 13:00:40 +0100
> Michael,
> 
> Thanks, that did fix the problem.  Out of curiosity (strictly academic
> as my stylesheet does what I need it to), is there a more elegant
> solution to the problem?  Or is the stylesheet I wrote along 
> the correct
> lines?
> 
One could make minor tweaks but nothing radical. When using the identity
template I don't normally apply templates to attributes unless there are
changes to be made, I normally copy them using <xsl:copy-of select="@*"/>.
And where the body of a template rule consists entirely of an xsl:choose, I
would normally split it into multiple template rules, moving the "test"
condition to be part of the match pattern. (You can't do this in 1.0 if it
references a variable, but yours doesn't).

Michael Kay

> 
> -----Original Message-----
> From: Michael Kay [mailto:mhk@xxxxxxxxx] 
> Sent: Saturday, July 31, 2004 5:20 AM
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: RE: [xsl] RE: unwanted and non prefix namespaces in output
> 
> I don't know what XSLT processor you're using, but the output 
> I'm seeing
> from Saxon (which I believe is correct) starts:
> 
> <sequence xmlns:ads="http://schemas.microsoft.com/ads/2003/sequence";
> version="1" description="foo" command="bar">
>   
>    <sequence version="1" description="Image" command="WIN2000">
>     
>       <task xmlns="http://schemas.microsoft.com/ads/2003/sequence";>
> 
> The first <sequence> element is generated from a literal 
> result element
> in your stylesheet. It is in no namespace because the 
> stylesheet doesn't
> put it in a namespace. It copies the declaration of xmlns:ads from the
> stylesheet because that's what literal result elements do.
> 
> The second <sequence> element is the same, but it doesn't redeclare
> xmlns:ads because that would be redundant.
> 
> The <task> element is generated by copying from the source 
> document. The
> element is in the ads/2003 namespace because it stays in the same
> namespace when you copy it. The original <task> element has 
> an in-scope
> namespace with prefix "" and uri "http://....ads/2003/...";, so the
> copied element has one too.
> 
> I think, if I understand your problem description, that you probably
> want to write <xsl:copy> where you currently write 
> <sequence>. That way
> you will get the namespaces that are in scope for the source element,
> not those that are in scope in the stylesheet.
> 
> You made a lot of headway in four hours...
> 
> Michael Kay 
> 
> > -----Original Message-----
> > From: Joel Friedman [mailto:jfriedman@xxxxxxxxxxxx]
> > Sent: 31 July 2004 07:09
> > To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> > Subject: [xsl] RE: unwanted and non prefix namespaces in output
> > 
> > I am very new to xslt (approx 4 hours) but I have managed to
> > (mostly) do
> > the simple task I am trying to perform.
> >  
> > I am attempting to take an xml file in this format (greatly 
> shortened 
> > for simplicity):
> >  
> > <?xml version="1.0" encoding="utf-16"?> <sequence version="1" 
> > description="foo" command="bar"
> > xmlns="http://schemas.microsoft.com/ads/2003/sequence";>
> > 
> >   <sequence version="1" description="Image" command="WIN2000"
> > xmlns="http://schemas.microsoft.com/ads/2003/sequence";>
> >     <task>
> >       <command>foo</command>
> >       <parameters>
> >         <parameter>bar</parameter>
> >       </parameters>
> >     </task>
> >    <task>
> >     ...
> >    </task
> >   </sequence>
> > 
> >   <sequence version="1" description="Patch" command="WIN2000"
> > xmlns="http://schemas.microsoft.com/ads/2003/sequence";>
> >     <task>
> >       <command>foo</command>
> >       <parameters>
> >         <parameter>bar</parameter>
> >       </parameters>
> >     </task>
> >     <task>
> >      ...
> >     </task
> >   </sequence>
> > 
> >   <sequence version="1" description="Patch" command="WIN2K3"
> > xmlns="http://schemas.microsoft.com/ads/2003/sequence";>
> >     <task>
> >       <command>foo</command>
> >       <parameters>
> >         <parameter>bar</parameter>
> >       </parameters>
> >     </task>
> >    <task>
> >     ...
> >    </task
> >   </sequence>
> > 
> >  <sequence version="1" description="foo" command="bar"
> > xmlns="http://schemas.microsoft.com/ads/2003/sequence";>
> >    ...
> >  </sequence>
> > 
> >   ...
> >  
> > </sequence>
> >  
> >  
> > And apply this XSL:
> >  
> > <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
> >  
> > xmlns:ads="http://schemas.microsoft.com/ads/2003/sequence";
> >                 version="1.0">
> >  
> >   <xsl:output method="xml" indent="yes"/>
> >   <xsl:variable name="osName"
> > select="ads:sequence/ads:sequence/@command"/>
> >     
> >   <xsl:template match="/">
> >     <xsl:apply-templates select="ads:sequence"/>
> >   </xsl:template>
> >  
> >   <xsl:template match="ads:sequence">
> >     <xsl:choose>
> >       <xsl:when test="(@description='Patch')">
> >         <xsl:if test="@command=$osName">
> >           <sequence>
> >             <xsl:apply-templates select="@*|node()"/>
> >           </sequence>
> >           </xsl:if>
> >       </xsl:when>
> >       <xsl:otherwise>
> >         <sequence>
> >           <xsl:apply-templates select="@*|node()"/>
> >         </sequence>
> >       </xsl:otherwise>
> >     </xsl:choose>
> >   </xsl:template>
> >  
> >   <xsl:template match="@*|node()">
> >     <xsl:copy>
> >       <xsl:apply-templates select="@*|node()"/>
> >     </xsl:copy>
> >   </xsl:template>
> >   
> > </xsl:stylesheet>
> >  
> >  
> > Basically I'm trying to fetch the OS Name from the command 
> attribute 
> > of the second sequence (fixed location)  Then the if OS matches the 
> > command attribute for the sequence with a description of 
> 'Patch', copy
> 
> > it over.
> > Also copy over everything else that isn't a Patch sequence.  So 
> > basically my output should be identical to my input minus the Patch 
> > sequence where the OS does not match.  My problem enlies that every 
> > 'task ' element has the namespace added to it but the 
> sequence element
> 
> > does not.
> >  
> > ..sample output:
> >  
> > <?xml version="1.0" encoding="UTF-16"?> <sequence version="1" 
> > description="foo" command="bar">
> >  
> >  <sequence version="1" description="Image" command="WIN2000">
> >   <task  xmlns="http://schemas.microsoft.com/ads/2003/sequence";>
> >    <command>foo</command>
> >    <parameters>
> >     <parameter>bar</parameter>
> >    </parameters>
> >   </task>
> >  
> >  
> > The exclude-result-prefixes="ads" squashed my namespace on the root 
> > sequence element (which I don't want).  I need the 
> namespace to only 
> > be defined on all sequence blocks.  Just like the input.  The logic 
> > part of not copying over the block I do not need does work.  It's 
> > probably not the best way, but it is functional.  Forgive 
> me if I did 
> > not use the correct XSL grammar while trying to explain my problem.
> >  
> > Anybody have an idea of a direction I should look in for a solution?
> >  
> > Thanks in advance,
> >  
> > --Joel
> > 
> > ________________________________
> > 
> > From: Joel Friedman
> > Sent: Saturday, July 31, 2004 2:07 AM
> > To: 'xsl-list@xxxxxxxxxxxxxxxxxxxxxx'
> > Subject: unwanted and non prefix namespaces in output
> > 
> > 
> > I am very new to xslt (approx 4 hours) but I have managed to
> > (mostly) do
> > the simple task I am trying to perform.
> >  
> > I am attempting to take an xml file in this format (greatly 
> shortened 
> > for simplicity):
> >  
> > <?xml version="1.0" encoding="utf-16"?> <sequence version="1" 
> > description="foo" command="bar"
> > xmlns="http://schemas.microsoft.com/ads/2003/sequence";>
> > 
> >   <sequence version="1" description="Image" command="WIN2000"
> > xmlns="http://schemas.microsoft.com/ads/2003/sequence";>
> >     <task>
> >       <command>foo</command>
> >       <parameters>
> >         <parameter>bar</parameter>
> >       </parameters>
> >     </task>
> >    <task>
> >     ...
> >    </task
> >   </sequence>
> > 
> >   <sequence version="1" description="Patch" command="WIN2000"
> > xmlns="http://schemas.microsoft.com/ads/2003/sequence";>
> >     <task>
> >       <command>foo</command>
> >       <parameters>
> >         <parameter>bar</parameter>
> >       </parameters>
> >     </task>
> >     <task>
> >      ...
> >     </task
> >   </sequence>
> > 
> >   <sequence version="1" description="Patch" command="WIN2K3"
> > xmlns="http://schemas.microsoft.com/ads/2003/sequence";>
> >     <task>
> >       <command>foo</command>
> >       <parameters>
> >         <parameter>bar</parameter>
> >       </parameters>
> >     </task>
> >    <task>
> >     ...
> >    </task
> >   </sequence>
> > 
> >  <sequence version="1" description="foo" command="bar"
> > xmlns="http://schemas.microsoft.com/ads/2003/sequence";>
> >    ...
> >  </sequence>
> > 
> >   ...
> >  
> > </sequence>
> >  
> >  
> > And apply this XSL:
> >  
> > <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
> >  
> > xmlns:ads="http://schemas.microsoft.com/ads/2003/sequence";
> >                 version="1.0">
> >  
> >   <xsl:output method="xml" indent="yes"/>
> >   <xsl:variable name="osName"
> > select="ads:sequence/ads:sequence/@command"/>
> >     
> >   <xsl:template match="/">
> >     <xsl:apply-templates select="ads:sequence"/>
> >   </xsl:template>
> >  
> >   <xsl:template match="ads:sequence">
> >     <xsl:choose>
> >       <xsl:when test="(@description='Patch')">
> >         <xsl:if test="@command=$osName">
> >           <sequence>
> >             <xsl:apply-templates select="@*|node()"/>
> >           </sequence>
> >           </xsl:if>
> >       </xsl:when>
> >       <xsl:otherwise>
> >         <sequence>
> >           <xsl:apply-templates select="@*|node()"/>
> >         </sequence>
> >       </xsl:otherwise>
> >     </xsl:choose>
> >   </xsl:template>
> >  
> >   <xsl:template match="@*|node()">
> >     <xsl:copy>
> >       <xsl:apply-templates select="@*|node()"/>
> >     </xsl:copy>
> >   </xsl:template>
> >   
> > </xsl:stylesheet>
> >  
> >  
> > Basically I'm trying to fetch the OS Name from the command 
> attribute 
> > of the second sequence (fixed location)  Then the if OS matches the 
> > command attribute for the sequence with a description of 
> 'Patch', copy
> 
> > it over.
> > Also copy over everything else that isn't a Patch sequence.  So 
> > basically my output should be identical to my input minus the Patch 
> > sequence where the OS does not match.  My problem enlies that every 
> > 'task ' element has the namespace added to it but the 
> sequence element
> 
> > does not.
> >  
> > ..sample output:
> >  
> > <?xml version="1.0" encoding="UTF-16"?> <sequence version="1" 
> > description="foo" command="bar">
> >  
> >  <sequence version="1" description="Image" command="WIN2000">
> >   <task  xmlns="http://schemas.microsoft.com/ads/2003/sequence";>
> >    <command>foo</command>
> >    <parameters>
> >     <parameter>bar</parameter>
> >    </parameters>
> >   </task>
> >  
> >  
> > The exclude-result-prefixes="ads" squashed my namespace on the root 
> > sequence element (which I don't want).  I need the 
> namespace to only 
> > be defined on all sequence blocks.  Just like the input.  The logic 
> > part of not copying over the block I do not need does work.  It's 
> > probably not the best way, but it is functional.  Forgive 
> me if I did 
> > not use the correct XSL grammar while trying to explain my problem.
> >  
> > Anybody have an idea of a direction I should look in for a solution?
> >  
> > Thanks in advance,
> >  
> > --Joel

Current Thread