Encoding 使用MSXML的XSLT转换不会';不要使用正确的编码

Encoding 使用MSXML的XSLT转换不会';不要使用正确的编码,encoding,xslt,msxml,Encoding,Xslt,Msxml,我使用MSXML3.0应用XSLT转换。每个转换都有一个xsl:output指令,指定UTF-8作为编码。比如说, <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" ... xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:str="ht

我使用MSXML3.0应用XSLT转换。每个转换都有一个
xsl:output
指令,指定
UTF-8
作为编码。比如说,

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
                ...
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:str="http://exslt.org/strings"
                xmlns:math="http://exslt.org/math"
                extension-element-prefixes="str math">
  <xsl:output encoding="UTF-8" indent="yes" method="xml" />
  ...
</xsl:stylesheet>
这是MSXML中的错误吗

出于各种原因,我非常希望使用
UTF-8
。有解决办法吗?或者我必须自己将转换后的结果转换为
UTF-8
并修补编码属性吗


更新:我已经解决了这个问题,接受了
UTF-16
编码并预先添加了一个字节顺序标记,以满足转换结果的下游用户,但是我仍然对如何获得UTF-8输出感兴趣。

您可能将输出发送到DOM树或字符流,而不是字节流。如果是这样的话,那么进行编码的不是MSXML,而不管进行最终编码的是什么,都不知道xsl:output指令(或者实际上是XSLT指令)。

补充Michael Kay所说的(当然是重点),下面是一个JScript示例,说明如何在过程中使用XSLT序列化转换为流:

// command line args
var args = WScript.Arguments;
if (args.length != 3) {
    WScript.Echo("usage: cscript msxsl.js in.xml ss.xsl out.xml");
    WScript.Quit();
}
xmlFile = args(0);
xslFile = args(1);
resFile = args(2);

// DOM objects
var xsl = new ActiveXObject("MSXML2.DOMDOCUMENT.6.0");
var xml = xsl.cloneNode(false);

// source document
xml.validateOnParse = false;
xml.async = false;
xml.load(xmlFile);
if (xml.parseError.errorCode != 0)
    WScript.Echo ("XML Parse Error : " + xml.parseError.reason);

// stylesheet document
xsl.validateOnParse = false;
xsl.async = false;
xsl.resolveExternals = true;
//xsl.setProperty("AllowDocumentFunction", true);
//xsl.setProperty("ProhibitDTD", false);
//xsl.setProperty("AllowXsltScript", true);
xsl.load(xslFile);
if (xsl.parseError.errorCode != 0)
    WScript.Echo ("XSL Parse Error : " + xsl.parseError.reason);

// output object, a stream
var stream = WScript.createObject("ADODB.Stream");
stream.open();
stream.type = 1;
xml.transformNodeToObject( xsl, stream );
stream.saveToFile( resFile );
stream.close();
您可以使用此输入进行测试:

<Urmel>
    <eins>Käse</eins>
    <deux>café</deux>
    <tre>supplì</tre>
</Urmel>

卡塞
咖啡馆
补充
这个样式表:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output encoding="UTF-8"/>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>


我认为将JScript示例应用到C++是很容易的。

< P>正如你注意到的,BSTR都是UTF 16。然而,我认为迈克尔·路德维格可能在这里有所发现。你试过用这种方法吗

HRESULT IXMLDOMDocument::transformNodeToObject(
    IXMLDOMNode *stylesheet,
    VARIANT outputObject);

您应该能够只使用CreateStreamOnHGlobal,将结果IStream ptr存储到变量中,并将其作为outputObject参数传入。理论上。不过,我实际上还没有尝试过:)

transformNode的输出是一个BSTR。MSXML似乎没有提供字节流选项。在输出中设置编码属性的是
transformNode
调用。BSTR通常是
UTF-16
,但它们可以使用单字节编码,如
UTF-8
。事实上,我用UTF-8字节的BSTR创建了IXMLDOMDocument对象。编码问题在于转换输出的序列化。如果使用.NET,则需要使用Encoding类。自从你提到BSTR,我怀疑你在使用C++。我不熟悉它的库,但找到一种方法把BSTR转换成UTF-8字节流。@道格D:是的,我使用C++,而不是.NET。编码不仅仅是一个后处理步骤,因为XSLT转换正在输出本身中添加
UTF-16
encoding/charset属性。因此,我似乎必须转换到UTF-8并调整实际输出。是的,可能。您可以使用我没有足够小心的RTFM来阻止xml声明。我没有意识到
transformNodeToObject
可以输出除另一个DOM对象之外的其他对象。三个答案都指向这个方向,但只有这一个清楚地表明我使用了错误的方法。很抱歉,在奖金到期之前,我没有看到您的回复。不用担心——很高兴能提供帮助:)谢谢Lumi——这正是我在用JavaScript将XSL结果保存到文件时保持XSL中设置的编码所需要的+1.
HRESULT IXMLDOMDocument::transformNodeToObject(
    IXMLDOMNode *stylesheet,
    VARIANT outputObject);