Re: [xsl] Re: encoding error when using cdata

Subject: Re: [xsl] Re: encoding error when using cdata
From: Michael Ludwig <mlu@xxxxxxxxxxxxx>
Date: Tue, 31 Mar 2009 14:58:18 +0200
Mike Stroud schrieb:
What I don't understand is why the resultant XML file is encoded like
this: <?xml version="1.0" encoding="UTF-16"?>. I can't seem to change
it! What I want is WINDOWS-1252, but I end up with UTF-16 no matter
what I do (The source XML document is UTF-8). My XSL looks like this:

<?xml version="1.0" encoding="Windows-1252"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
<xsl:output indent="yes" method="xml"
  cdata-section-elements="Name LongDesc"/>

Stumbled myself in this MSXML issue. When using this processor, by default the result of the transformation is encoded in UTF-16, no matter what you specify in <xsl:output>.

By the way, if you're still listening, while you do specify the encoding
of your XSL stylesheet, you do not specify your desired output encoding,
which you'd do as follows:

<xsl:output encoding="Windows-1252"/>

One way to control the output encoding from XSLT (using the Perl API for
Win32, same thing as JScript, VBScript etc) uses a binary ADODB.Stream,
as can be seen from the appended file.

Michael Ludwig

# more /t2 \MILU\bin\msxsl.pl
use strict;
use warnings;
use Win32::OLE;

my( $xmlfile, $xslfile, $outfile) = @ARGV;
die "Aufruf: $0 XML XSL OUT\n"
  unless $xmlfile && $xslfile && $outfile;

my $class_domdoc   = 'MSXML2.DOMDocument.4.0';
my $class_domdocft = 'MSXML2.FreeThreadedDOMDocument.4.0';
my $class_xsltmpl  = 'MSXML2.XSLTemplate.4.0';

my $xmldoc = Win32::OLE->new( $class_domdoc)
  or die "new($class_domdoc): " . Win32::OLE->LastError;
$xmldoc->LetProperty( async => 0);
$xmldoc->load( $xmlfile)
  or die "load($xmlfile): " . $xmldoc->{parseError}{reason};

# Doku f|r load:
# http://msdn.microsoft.com/en-us/library/ms762722(VS.85).aspx

my $xsldoc = Win32::OLE->new( $class_domdocft)
  or die "new($class_domdocft): " . Win32::OLE->LastError;
$xsldoc->LetProperty( async => 0);
$xsldoc->load( $xslfile)
  or die "load($xmlfile): " . $xmldoc->{parseError}{reason};

my $tmpl = Win32::OLE->new( $class_xsltmpl)
  or die "new($class_xsltmpl): " . Win32::OLE->LastError;
$tmpl->LetProperty( stylesheet => $xsldoc);

my $stream = Win32::OLE->new( 'ADODB.Stream');
$stream->LetProperty( mode => 3); # read/write
$stream->LetProperty( type => 1); # binary
$stream->open;

my $proc = $tmpl->createProcessor
  or die "kein XSLT-Prozessor aus $xslfile zu erzeugen";
$proc->LetProperty( input  => $xmldoc);
$proc->LetProperty( output => $stream); # f|r ADODB.Stream
$proc->transform
  or die "Transformation: " . Win32::OLE->LastError;
# print $proc->{output}; # ohne ADODB.Stream
$stream->saveToFile( $outfile, 2); # create/overwrite
$stream->close;

Current Thread