1

質問表を表示し、質問オプションを保存するために、xsltおよびxmlファイルを動的に作成しています(ドロップダウン用)。実際のファイルに書き込む代わりに、ストリームを使用したいと思います。だからこれは私がそれをしている方法です:

XmlReader xslt_reader;
XmlReader xml_reader;

PageLoad(){
  Fn_CreateXSL();
  Fn_CreateXML();
  LoadQuestionnaire();
}

Fn_CreateXSL(){
   xslt_stream = new MemoryStream();

   XmlTextWriter objXSLTWriter = new XmlTextWriter(xslt_stream, Encoding.UTF8);

   objXSLTWriter.Formatting = Formatting.Indented;
   objXSLTWriter.WriteStartDocument();
    ..........
   objXSLTWriter.WriteEndDocument();
   xslt_stream.Seek(0, SeekOrigin.Begin);
   xslt_reader = XmlReader.Create(xslt_stream);
}

Fn_CreateXML(){
   xmlt_stream = new MemoryStream();

   XmlTextWriter objXMLTWriter = new XmlTextWriter(xmlt_stream, Encoding.UTF8);

   objXMLTWriter.Formatting = Formatting.Indented;
   objXMLTWriter.WriteStartDocument();
    ..........
   objXMLTWriter.WriteEndDocument();
   xmlt_stream.Seek(0, SeekOrigin.Begin);
   xmlt_reader = XmlReader.Create(xmlt_stream);
}

LoadQuestionnaire(){
  XslCompiledTransform var_xsl_trans = new XslCompiledTransform();

  // also tried var_xsl_trans.Load(xslt_reader, null, new XmlUrlResolver());
  var_xsl_trans.Load(xslt_reader); // XSLT Compile Error occurs

  StringWriter sw = new StringWriter();

  var_xsl_trans.Transform(xml_reader, null, sw);
}

しかし、ロードしようとすると「XSLTコンパイルエラー」が発生します。何か考えはありますか?

4

2 に答える 2

1

これが私のために働くアプローチです。

XmlWriter->MemoryStream->XmlReader を使用する代わりにXElement、Microsoft によって導入された .NET 3.5 の LINQ を使用します。クラスのLoadTransformメソッドの両方に、 XML を渡すためのパラメーターとして受け取るオーバーロードがあります。このインターフェイスにはメソッドが 1 つしかなく、そのようなメソッドがあります。Microsoft が でこのインターフェイスを実装していると宣言しなかった理由はわかりません。おそらく彼らは忘れていました:-)。そこで、この見落としを補うために、6 回線のコンバーター クラスを実装しました。以下に表示されます。これは、OP の Page_Load() の類似物です。XslCompiledTransformIXPathNavigableXPathNavigator CreateNavigator()XElementXElementXNavigable

public void Generate()
{
    XElement inputXml = CreateInputXml();
    XElement transformXslt = CreateTransformXslt();

    XslCompiledTransform transform = new XslCompiledTransform();
    transform.Load(new XNavigable(transformXslt), null, null);

    MemoryStream outputStream = new MemoryStream(); 
    transform.Transform(new XNavigable(inputXml), null, outputStream);

    byte[] outputBytes = outputStream.ToArray();
    string outputString = Encoding.UTF8.GetString(outputBytes);
}

StringWriter が常に UTF-16 でエンコードされた XML を出力として作成していたため、MemoryStream代わりに使用します。StringWriter基になる文字列は1文字あたり16ビットであるため、UTF-16はStringWriterによって課されていると思います。MemoryStream を使用すると、エンコーディングを制御できます。

CreateInputXml完全を期すために、ここに my メソッドとメソッドのコードを示しCreateTransformXsltます。それらは単なる例です。もちろん、XElement.Add()メソッドを使用してコンテンツを生成することもできます。すべてのノードがリストされたコンストラクターを使用して、すばやくハードコーディングしました。

    private static XElement CreateTransformXslt()
    {
        //XSL to substitute <placeholder/> with <realElement/> and copy everything else.
        //<stylesheet version="1.0" xmlns="http://www.w3.org/1999/XSL/Transform">
        //  <output indent="yes" />
        //  <template match="@* | node()">
        //    <copy>
        //      <apply-templates select="@* | node()" />
        //    </copy>
        //  </template>
        //  <template match="placeholder">
        //    <realElement xmlns="" />
        //  </template>
        //</stylesheet>
        XNamespace xsl = "http://www.w3.org/1999/XSL/Transform";
        XNamespace empty = "";
        XElement transformXslt = new XElement(xsl + "stylesheet", new XAttribute("version", "1.0"),
            new XElement(xsl + "output", new XAttribute("indent", "yes")),
            //new XElement(xsl + "strip-space", new XAttribute("elements", "*")),
            new XElement(xsl + "template", new XAttribute("match", "@* | node()"),
                new XElement(xsl + "copy",
                    new XElement(xsl + "apply-templates", new XAttribute("select", "@* | node()"))
                )
            ),
            new XElement(xsl + "template", new XAttribute("match", "placeholder"),
                new XElement("realElement")
            )
        );
        return transformXslt;
    }

    private static XElement CreateInputXml()
    {
        XElement origXml = new XElement(new XElement("Root",
                                            new XElement("Child1", "data1"),
                                            new XElement("placeholder"),
                                            new XElement("Child2", "data2")));
        return origXml;
    }

xsl:strip-space elements="*"上記のコードの落とし穴の 1 つは、XSL で使用してはならないということです。以上がコメントです。これはXslCompiledTransform、入力 xml が として渡されたときにスペースを削除する際に問題があるためIXPathNavigableです。XmlReaderエラーメッセージでは、ストリッピングが必要な場合に使用することを提案していました. Web ページを生成するためにスペースの除去が重要だとは思いません。

最後に、冒頭で述べたコンバーター クラスを次に示します。

class XNavigable : IXPathNavigable
{
    XElement _xElement;
    public XNavigable(XElement xElement)
    {
        _xElement = xElement;
    }

    public XPathNavigator  CreateNavigator()
    {
            return _xElement.CreateNavigator();
    }
}
于 2012-10-05T04:08:46.253 に答える
0

コメントで@kevinが言及したように、次のようにして問題を修正しましたが、なぜそれが機能したのかよくわかりません(いくつかのアイデアがありますが、よくわかりません)

xmlt_stream.Seek(0, SeekOrigin.Begin); の前に objXMLTWriter.Flush() を追加します。

于 2012-10-09T17:05:17.547 に答える