用xsl格式化MSXML2操作的XML文件

MSXML2::IXMLDOMDocument2Ptr CXMLDOMFile::XMLNormalize( MSXML2::IXMLDOMDocument2Ptr pXMLDocOld)
{
// Style for normalization
char pszStyle[]=
"<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">\
<xsl:output method=\"xml\" indent=\"yes\" encoding=\"UTF-8\" standalone=\"yes\"/>\
<xsl:template match=\"@* | node()\">\
<xsl:copy>\
<xsl:apply-templates select=\"@* | node()\"/>\
</xsl:copy>\
</xsl:template>\
</xsl:stylesheet>";


// Create a style dom document                
MSXML2::IXMLDOMDocument2Ptr pStyle=NULL;
pStyle.CreateInstance( __uuidof( MSXML2::DOMDocument26) );
BSTR styleStr = _bstr_t(pszStyle);
pStyle->loadXML(styleStr);//这里用loadXML的话由于使用BSTR类型(默认为UTF-16编码),加载进的XML将被自动转//换为UTF-16编码格式


// Create a new doc for return
MSXML2::IXMLDOMDocumentPtr pNew=NULL;
pNew.CreateInstance( __uuidof( MSXML2::DOMDocument26) );


// Transform
pNew->loadXML(pXMLDocOld->transformNode(pStyle));//transformNode将返回BSTR类型数据
//这里用loadXML的话由于使用BSTR类型(默认为UTF-16编码),加载进的XML将被自动转//换为UTF-16编码格式,因此导致输出的文件只能是UTF-16编码文件,破坏了原有的文件编码

return pNew;

}

对上述问题,解释与解决方案如下:

MSXML DOM 错误
两个常见的错误从 XML 文档对象模型 (DOM) 接口方法返回的是:
文本内容中找到无效的字符。
-和-
不支持从当前加密到指定的编码开关。
IXMLDOMDocument接口的load方法,这些错误通常发生在下列情况下:
  • 指定没有编码、 找到没有字节顺序标记开头的 XML 文件和数据中包含特殊字符 encoded in UTF-16 format (such as Swedish character å, or 0xE5) rather than the default UTF-8 (0xC3 0xA5) format.
  • 指定的编码与 XML 数据的实际编码不匹配。
一个好的做法是始终指定正确的编码在 XML 声明中,而不是接受默认的编码。

使用 MSXML 分析器版本 2.5,2.5 SP1 和 2.6, loadXML方法的IXMLDOMDocument只能加载 utf-16 或 ucs-2 编码数据。任何尝试加载 XML 数据使用另一种编码格式导致以下错误:
不支持从当前编码到指定的编码的切换。
MSXML 3.0 (Msxml3.dll) 的发布,这种限制将被删除,并以下代码运行不会出错:
hr = pXMLDoc->loadXML("<?xml version=\"1.0\" encoding=\"UTF-8\"?><tag1>Abcdef</tag1>");
				
注意: 为 utf-16 编码,而不在开始时的字节顺序标记的情况下, xml属性的IXMLDOMDocument接口将写出 XML 数据。这可能会导致的编码问题。

XSL 或 XSLT 文件的 XML 编码的信息,如下所示指定在其中调用IXMLDOMNode接口的transformNode方法时,您还可能收到以下错误:
<xsl:output method="xml" encoding="UTF-8" />
				
TransformNode方法返回 BSTR 即根据定义的 utf-16 编码数据。保留的编码更好的方法是调用transformNodeToObject方法,并将结果写入流或到新的 XML 文档存储,然后予以保存。


因此上述代码应修改为:

MSXML2::IXMLDOMDocument2Ptr CXMLDOMFile::XMLNormalize( MSXML2::IXMLDOMDocument2Ptr pXMLDocOld)
{
// Style for normalization
char pszStyle[]=
"<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\" encoding=\"utf-8\">\
<xsl:output method=\"xml\" encoding=\"utf-8\" indent=\"yes\" />\//指定使用UTF-8编码存储xml文件
<xsl:template match=\"@* | node()\">\
<xsl:copy>\
<xsl:apply-templates select=\"@* | node()\"/>\
</xsl:copy>\
</xsl:template>\
</xsl:stylesheet>";


// Create a style dom document                
MSXML2::IXMLDOMDocument2Ptr pXMLStyle=NULL;
pXMLStyle.CreateInstance( __uuidof( MSXML2::DOMDocument26) );
BSTR styleStr = _bstr_t(pszStyle);
pXMLStyle->loadXML(styleStr);


// Create a new doc for return
MSXML2::IXMLDOMDocumentPtr pNew=NULL;
pNew.CreateInstance( __uuidof( MSXML2::DOMDocument26) );


// Transform
IDispatch *pDisp = NULL;
pNew->QueryInterface(IID_IDispatch, (void**)&pDisp);


VARIANT varDisp;
VariantInit(&varDisp);
V_VT(&varDisp) = VT_DISPATCH;
V_DISPATCH(&varDisp) = pDisp;
pDisp = NULL;

pXMLDocOld->transformNodeToObject(pXMLStyle,varDisp);

//这样修改之后,最终的pNew指向的XML文件格式才符合上述xsl中指定的utf-8编码

return pNew;
}


参考资料:http://msdn.microsoft.com/en-us/library/ms757821(v=vs.85).aspx

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值