2013-04-18 12 views
5

Delphi XE2では、受信したXMLファイルに対してxslt変換を行って、すべての名前空間情報を削除します。
問題:これは、名前空間の情報を削除する機能があるXSLT変換でutf-8 XMLをutf-16に変換できないようにしますか?

<?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>[email protected]</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:[email protected]tellbv.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> 

:それはこれは私がExchangeサーバーから取り戻すXMLである

<?xml version="1.0" encoding="utf-16"?> 

<?xml version="1.0" encoding="utf-8"?> 

を変更します。

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の文書です:グーグルで "XSL UTF-8、UTF-16" の後

<?xml version="1.0" encoding="UTF-16"?> 
<Envelope> 
[snip] 
</Envelope> 

が、私はいくつか試してみました:

  • 変更行を(例えば、いずれかに

    <xsl:output method="xml" indent="no"> 
    

    Output DataTable XML in UTF8 rather than UTF16

    :動作しませんでした

    <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プロセッサに指示」)

  • 開始xmlタグを抜けて、しかし、もし私そしてちょうどPR

    <xsl:output method="xml" omit-xml-declaration="yes" indent="no" /> 
    

    にライン(例えばXslCompiledTransform uses UTF-16 encoding

    <xsl:output method="xml" indent="no"/> 
    

    を変更

    epend

    <?xml version="1.0" encoding="utf-8"?> 
    

    実際のutf変換が行われないので、私は文字を失います。

  • IXMLDOMdocument2は、この問題を解決する方法任意のアイデア

Encoding性質を持っていませんか?

備考/背景:

  • 他のすべての場合は、UTF-8にUTF-16 XMLデータを変更するオプションが多分まだあります失敗したが、それは全く異なるアプローチです。

  • 私はEWS経由でExchangeサーバと通信しているため、utf-16にhttpリクエストヘッダーを設定すると動作しません:Exchangeは私にコンテンツタイプのテキスト/ xml; charset = utf-16 'は予想されるタイプ' text/xmlではありません。 charset = utf-8 'となります。EWSはutf-8を返す(投稿の開始を参照)。

+2

@Gsergの書式設定の編集に感謝しました。私は箇条書きのコードブロックに取り組んでいました。 –

答えて

1

あなたの中に元のコードを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 

あなたはSaveToXMLを交換、/ファイルをストリーミングする保存したい場合は今変数UTF8は、UTF-8エンコーディングに変換されたXMLが含まれている必要があります

2

問題は、それが文字列を返すとMSXMLでそのような文字列がUTF-16でエンコードされ、transformNode方法の使用です。そのため、結果として空のMSXML DOMドキュメントを作成し、the transformNodeToObject methodを使用して空のDOMドキュメントを2番目の引数として渡し、ファイルまたはストリームに結果ドキュメントを保存し、エンコーディングをxsl:outputディレクティブに指定する必要があります。

+0

DOMはUTF-16を使って内部実装されているため、ターゲットDOMドキュメントの変換の結果はUTF-16でエンコードされることになります。エンコーディング自体は入力/出力フィルタのためのタスクでなければならないので、私はそれを呼び出す必要があります。 'iXMLDocument.SaveToXML(AUTF8String)' – pf1957

+0

MSXMLには 'SaveToXML'というメソッドはありません。 DOM文書に 'save'という名前のメソッドがあり、空の状態で作成されたDOM文書でそのメソッドを使用してから、' transformNodeToObject'メソッドに渡すことをお勧めします。そのようにして、ファイルまたはストリームに保存する場合、エンコーディングは意図したとおりにする必要があります。これは 'transformNode'を使うと不可能です。 –

+0

私は知っています。私はMSXMLを直接呼び出すのではなく、 'IXMLDocument' /' IXMLNode'を使って呼び出します。オーバーロードされたメソッド 'TransformNode'があり、そのうちの1つは' transformNodeToObject'を呼び出します。私のコメントは、適切なエンコーディングを保証するために何らかの** save **操作を実行する必要性を懸念しています。それは簡単に保存することができます。 SaveToXMLを呼び出し、型UTF8Stringのvar引数を渡します。 – pf1957

関連する問題