Вы можете получить прогресс XmlCompiledTransform?

Я хочу прочитать 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 все равно загружает все это в память?

Надеюсь, в этом есть какой-то смысл, спасибо!

Адам.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
0
807
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Можно отправить сообщения 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);
    }
}

Я не собираюсь опускать его, потому что это умный ответ, и у меня нет лучшего ответа, но я должен сказать, что не уверен, что мне нравится помещать такую ​​логику кодирования в файл xsl, который предназначен для описания как отформатировать / преобразовать XML-документ. Это нехорошее разделение забот.

Neil Barnwell 16.12.2008 15:35

Не согласен. Вам не нужно добавлять логику кодирования в XSLT, вам нужно только добавить «трассирующие» сообщения в очень немногих местах, например начало одного матча-шаблона.

Dirk Vollmar 16.12.2008 16:33

(продолжение) Как еще вы могли бы информировать клиента о прогрессе и о том, где вы находитесь в процессе преобразования, не вставляя дополнительную «логику» в свой XSLT?

Dirk Vollmar 16.12.2008 16:34

Спасибо! Это решение отлично работает для меня. Теперь я знаю, что происходит внутри моих преобразований!

Brad J 06.09.2014 18:44

Другие вопросы по теме