在Delphi XE2中,我正在对收到的
XML文件进行xslt转换,以删除所有命名空间信息.
问题:它改变了
问题:它改变了
<?xml version="1.0" encoding="utf-8"?>
成
<?xml version="1.0" encoding="utf-16"?>
这是我从Exchange服务器返回的XML:
<?xml version="1.0" encoding="utf-8"?> <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> <s:Header> <h:ServerVersionInfo MajorVersion="14" MinorVersion="0" MajorBuildNumber="722" MinorBuildNumber="0" Version="Exchange2010" xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types" xmlns="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"/> </s:Header> <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <m:ResolveNamesResponse xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"> <m:ResponseMessages> <m:ResolveNamesResponseMessage ResponseClass="Success"> <m:ResponseCode>NoError</m:ResponseCode> <m:ResolutionSet TotalItemsInView="1" IncludesLastItemInRange="true"> <t:Resolution> <t:MailBox> <t:Name>developer</t:Name> <t:EmailAddress>developer@timetellbv.nl</t:EmailAddress> <t:RoutingType>SMTP</t:RoutingType> <t:MailBoxType>MailBox</t:MailBoxType> </t:MailBox> <t:Contact> <t:Culture>nl-NL</t:Culture> <t:DisplayName>developer</t:DisplayName> <t:GivenName>developer</t:GivenName> <t:EmailAddresses> <t:Entry Key="EmailAddress1">SMTP:developer@timetellbv.nl</t:Entry> </t:EmailAddresses> <t:ContactSource>ActiveDirectory</t:ContactSource> </t:Contact> </t:Resolution> </m:ResolutionSet> </m:ResolveNamesResponseMessage> </m:ResponseMessages> </m:ResolveNamesResponse> </s:Body> </s:Envelope>
Uses MSXML2_TLB; // IXMLDOMdocument class function TXMLHelper.RemoveNameSpaces(XMLString: String): String; const // An XSLT script for removing the namespaces from any document. // From http://wiki.tei-c.org/index.PHP/Remove-Namespaces.xsl cRemoveNSTransform = '<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">' + '<xsl:output method="xml" indent="no"/>' + '<xsl:template match="/|comment()|processing-instruction()">' + ' <xsl:copy>' + ' <xsl:apply-templates/>' + ' </xsl:copy>' + '</xsl:template>' + '<xsl:template match="*">' + ' <xsl:element name="{local-name()}">' + ' <xsl:apply-templates select="@*|node()"/>' + ' </xsl:element>' + '</xsl:template>' + '<xsl:template match="@*">' + ' <xsl:attribute name="{local-name()}">' + ' <xsl:value-of select="."/>' + ' </xsl:attribute>' + '</xsl:template>' + '</xsl:stylesheet>'; var Doc,XSL: IXMLDOMdocument2; begin Doc := ComsDOMDocument.Create; Doc.ASync := false; XSL := ComsDOMDocument.Create; XSL.ASync := false; try Doc.loadXML(XMLString); XSL.loadXML(cRemoveNSTransform); Result := Doc.TransFormNode(XSL); except on E:Exception do Result := E.Message; end; end; { RemoveNameSpaces }
但在此之后,它突然变成了一个utf-16文件:
<?xml version="1.0" encoding="UTF-16"?> <Envelope> [snip] </Envelope>
谷歌搜索“xsl utf-8 utf-16”后我尝试了几件事:
>更改线路(例如Output DataTable XML in UTF8 rather than UTF16)
<xsl:output method="xml" indent="no">
进入:
<xsl:output method="xml" encoding="utf-8" indent="no"/> <xsl:output method="xml" encoding="utf-8"/> <xsl:output encoding="utf-8"/>
那没用.
(这将是最佳解决方案,根据http://www.xml.com/pub/a/2002/09/04/xslt.html“编码属性实际上不仅仅是为结果文档添加编码声明;它告诉XSLT处理器使用该编码写出结果.”)
>更改线路(例如XslCompiledTransform uses UTF-16 encoding)
<xsl:output method="xml" indent="no"/>
成
<xsl:output method="xml" omit-xml-declaration="yes" indent="no" />
这会遗漏起始的xml标签,但如果我只是前置
<?xml version="1.0" encoding="utf-8"?>
我将丢失字符,因为没有进行实际的utf转换.
> IXMLDOMdocument2没有Encoding属性
任何想法如何解决这一问题?
备注/背景:
>如果所有其他方法都失败了,可能仍然可以选择将utf-16 XML数据更改为utf-8,但这是一种完全不同的方法.
>我正在尝试做所有utf-8,因为我通过EWS与Exchange服务器通信,并且将http请求标头设置为utf-16不起作用:Exchange告诉我内容类型’text / xml; charset = utf-16’不是预期的类型’text / xml; charset = utf-8′. EWS返回utf-8(见帖子的开头).
解决方法
要在原始代码中使用IXMLDocument,它应如下所示:
var iInp,iOtp,iXsl: IXMLDocument; Utf8: UTF8String; begin iInp := LoadXMLData(XMLString); iXsl := LoadXMLData(cRemoveNSTransfrom); iOtp := NewXMLDocument; iInp.Node.TransformNode(iXsl.Node,iOtp); iOtp.SaveToXML(Utf8); end
现在变量Utf8应包含UTF-8编码的转换XML,如果要保存为流/文件,请将SaveToXML替换为
iOtp.Encoding := 'UTF-8'; iOtp.SaveToFile(....);