2017-02-03 6 views
4

グローバルパラメータを設定して、XSLT(Saxon-HE v9.7.0.14を使用)で生成されたxmlファイルにパスワードを設定しようとしています。cdata-section-elementsが動作しない

パスワードには任意の文字を使用できるため、CDATAセクションに入力する必要があります。

は私がパスワード要素の名前が含まれるように、私のXSLTの xsl:output要素の cdata-section-elements属性を設定することによって、これを達成しようとしています:これは動作しない

<xsl:output method="xml" indent="yes" cdata-section-elements="password"/> 

。私は以下のサンプルコード、入力、xslt、現在の出力と望ましい出力を以下に示しました。

CDATAセクションのパスワードを変更するにはどうすればよいですか?

プログラム:

using System; 
using System.IO; 
using Saxon.Api; 

namespace XsltTest { 
    class Program { 
     static void Main(string[] args) { 
      var xslt = new FileInfo(@"transform.xslt"); 
      var input = new FileInfo(@"input.xml"); 
      var output = new FileInfo(@"output.xml"); 
      var processor = new Processor(); 
      var compiler = processor.NewXsltCompiler(); 
      var executable = compiler.Compile(new Uri(xslt.FullName)); 
      var transformer = executable.Load(); 
      var destination = new DomDestination(); 
      using (var inputStream = input.OpenRead()) {    
       transformer.SetInputStream(inputStream, new Uri(Path.GetTempPath())); 
       transformer.SetParameter(
        new QName("password"), 
        new XdmAtomicValue("secret")); 
       transformer.Run(destination); 
      } 
      destination.XmlDocument.Save(output.FullName); 
     } 
    } 
} 

Transform.xslt:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"> 
    <xsl:output method="xml" indent="yes" cdata-section-elements="password"/> 
    <xsl:param name="password" /> 
    <xsl:template match="@* | node()"> 
    <bar> 
     <username> 
     <xsl:value-of select="//username"/> 
     </username> 
     <password> 
     <xsl:value-of select="$password"/> 
     </password> 
    </bar> 
    </xsl:template> 
</xsl:stylesheet> 

input.xmlに:

<?xml version="1.0" encoding="utf-8" ?> 
<foo> 
    <username>john</username> 
</foo> 

のOutput.xml:

<bar> 
    <username>john</username> 
    <password>secret</password> 
</bar> 

パスワードがCDATAセクションの内側に置かれていません。

望ましい結果:

<bar> 
    <username>john</username> 
    <password><![CDATA[secret]]></password> 
</bar> 

答えて

1

xsl:outputのオプションはシリアライザの動作に影響し、出力がシリアル化されていない場合は効果がありません。シリアライザではなくDomDestinationに書き込んでいます(DOMメソッドを使用してDOMをシリアル化していますが、XSLTのxsl:出力宣言については何も知らない)。

あなたの前提が間違っています:「パスワードには任意の文字を入れることができるので、CDATAセクションに入れる必要があります。」 cdata-section-elementsがなければ、特殊文字は&lt;&amp;のような実体参照を使ってシリアライズされますが、うまくいくはずです。

+0

ありがとうございます。私は 'DomDestination'の代わりに' Serializer'を使いました。 CDATAのないエンティティエンコーディングに関するコメントもありがとうございます。私は実際に既にCDATAのパスワードでXMLメッセージを送信しているシステムを置き換えています。私の前のチームはCDATAを使用する前に問題があると言いました。私たちは外部システムを制御してメッセージを読むことはできません。そのため、問題がXMLを適切に処理していないと判断し、CDATAを使用するときに問題なく動作することがわかりました。 – Ergwun

+0

無意識のうちに解析する人のためにXMLを生成することは、それを無力に生成する人が作成した(いわゆる)XMLを読むことよりほんの少しだけ面倒ではありません。 –

0

私はあなたのコードをテストし、それが正しく動作しているように見えます。

入力ライン

xsltproc --stringparam password "1>2Ä-34" Transform.xslt Input.xml 

所望の出力

<?xml version="1.0"?> 
<bar> 
    <username>john</username> 
    <password><![CDATA[1>2Ä-34]]></password> 
</bar> 

あなたは<xsl:param name="password" />を養うためにXSLTプロセッサにpasswordパラメータの入力を欠場返しますか?

+0

はここでそれを行うためのC#コードです。私はC#アプリケーションでSaxonを使用しています。 – Ergwun

+0

はい。私は知っていた。しかしそれは似ています:文字列パラメータ "password"をその値と共にXSLTに渡します。私の答えに記述されているように動作するはずです。 'xsl:stylesheet'レベルの空の' 'はそのような目的で決まります。 – zx485

0

Michael Kay's answerSerializerないDomDestinationへの書き込み時にcdata-section-elements属性のみ適用可能であることだったソリューションを、説明しました。私はxsltprocのを使用していないよ

static void Main(string[] args) { 
    var xslt = new FileInfo(@"transform.xslt"); 
    var input = new FileInfo(@"input.xml"); 
    var output = new FileInfo(@"output.xml"); 
    var processor = new Processor(); 
    var compiler = processor.NewXsltCompiler(); 
    var executable = compiler.Compile(new Uri(xslt.FullName)); 
    var transformer = executable.Load(); 
    var serializer = new Serializer(); 
    using (var writer = new StreamWriter(output.FullName)) 
    using (var inputStream = input.OpenRead()) { 
     serializer.SetOutputWriter(writer); 
     transformer.SetInputStream(inputStream, new Uri(Path.GetTempPath())); 
     transformer.SetParameter(
      new QName("password"), 
      new XdmAtomicValue("secret")); 
     transformer.Run(serializer); 
    }