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