我想读取xml文件,应用转换,然后写入另一个文件。我能想到的最好方法是:
using (XmlTextReader reader = new XmlTextReader(new FileStream(_source, FileMode.Open)))
using (XmlTextWriter writer = new XmlTextWriter(new StreamWriter(_destination)))
{
_xslTransform.Transform(reader, writer);
}
但我真的想要取得进展。如果我只是复制数据,我可以做这样的事情(这可能不是100%正确,但这样的事情):
using (BinaryReader reader = new BinaryReader(new FileStream(_source, FileMode.Open)))
using (BinaryWriter writer = new StreamWriter(_destination))
{
byte[] buffer = new byte[2048];
int read = 0;
int actual = 0;
long total = reader.BaseStream.Length;
while ((read = reader.Read(buffer, 0, buffer.Length)) > 0)
{
writer.Write(buffer, 0, read);
actual = (actual <= total ? actual + read : read);
updateProgress(Convert.ToInt32(actual / total * 100));
}
}
使用XslCompiledTransform时有一些方法可以做到这一点。我可以在写入文件之前先将其读入内存但是我想限制使用的内存量,或者XslCompiledTransform是否将其全部加载到内存中?
我希望这有点道理,谢谢!
亚当。
答案 0 :(得分:4)
一个选项是从转换中发送xsl:message消息并监听这些消息。
使用这种方法,您必须首先遍历输入文档并计算转换“迭代”的节点。这可以使用非常基本的XSLT来完成,它只在每个感兴趣的节点上发送消息。
然后 - 在实际转换期间 - 每次点击感兴趣的节点时,您都可以发送
<xsl:message terminate="no">progress:mynode</xsl:message>
进展信息。
可以使用消息侦听器在调用C#代码中拦截此消息。您可以将以下代码放入一个小类中以应用XSL转换。这只是一个用于说明的基本样本;我希望你明白这个想法:
protected event MessageListener progressMessageIntercepted;
public void AddProgressMessageListener(MessageListener listener)
{
progressMessageIntercepted += listener;
}
public void RemoveMessageListeners()
{
progressMessageIntercepted = null;
}
protected void MessageCallBack(object sender, XsltMessageEncounteredEventArgs e)
{
if (e.Message.StartsWith("progress:"))
{
if (progressMessageIntercepted != null)
{
progressMessageIntercepted(this, null);
}
}
}
protected void Transform(string inputFile, string outputFile, string xsltFile)
{
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(xsltFile);
XsltArgumentList parameters = new XsltArgumentList();
parameters.XsltMessageEncountered += new XsltMessageEncounteredEventHandler(MessageCallBack);
using (XmlWriter xmlWriter = XmlWriter.Create(outputFile))
{
xslt.Transform(inputFile, parameters, xmlWriter);
}
}