Tối ưu hóa duy trì trạng thái liên kết XSLT trong XmlNotepad

Nguyên nhân và giải pháp cho việc mất liên kết XSLT khi tải lại file XML

Trong XmlNotepad, việc tải lại file XML thường khiến thông tin về file XSLT đã liên kết trước đó bị mất, buộc người dùng phải thiết lập lại thủ công. Vấn đề này phát sinh do khi sự kiện ModelChangeType.Reloaded được kích hoạt, các thiết lập chuyển đổi XSLT trong control XsltViewer không được lưu trữ và khôi phục.

Kỹ thuật lưu trữ siêu dữ liệu liên kết XSLT

Giải pháp tập trung vào việc mở rộng lớp XmlCache để lưu trữ đường dẫn file XSLT và file đầu ra, đồng thời cải thiện logic xử lý sự kiện trong XsltViewer để tự động khôi phục các thông tin này.

Mở rộng lớp XmlCache

Thêm các thuộc tính để lưu trạng thái liên kết XSLT và sửa đổi phương thức Reload để bảo toàn chúng.

// Trong tệp Model/XmlCache.cs
public class XmlCache
{
    // Các thành viên hiện có...

    // Thuộc tính mới để lưu trạng thái XSLT
    public string AssociatedXsltPath { get; private set; }
    public string TransformOutputPath { get; private set; }
    public bool EnableAutoTransform { get; set; } = true;

    // Phương thức Reload được sửa đổi
    public void ReloadDocument()
    {
        // Lưu trạng thái hiện tại trước khi tải lại
        string savedXsltPath = this.AssociatedXsltPath;
        string savedOutputPath = this.TransformOutputPath;

        // Thực hiện logic tải lại tài liệu gốc
        this._loadedDocument = null;
        NotifyModelChanged(ModelChangeType.Reloaded, this._loadedDocument);

        // Khôi phục trạng thái sau khi tải lại
        this.AssociatedXsltPath = savedXsltPath;
        this.TransformOutputPath = savedOutputPath;
    }

    // Phương thức để thiết lập liên kết XSLT
    public void SetXsltAssociation(string xsltFilePath, string outputFilePath)
    {
        this.AssociatedXsltPath = xsltFilePath;
        this.TransformOutputPath = outputFilePath;
        // Có thể kích hoạt sự kiện thay đổi ở đây
    }
}

Cải thiện XsltViewer để khôi phục tự động

Sửa đổi trình xử lý sự kiện OnModelChanged trong control XsltViewer để kiểm tra và áp dụng lại đường dẫn XSLT từ cache.

// Trong tệp XmlNotepad/XsltViewer.cs
private void HandleModelChange(ModelChangedEventArgs args)
{
    try
    {
        if (string.IsNullOrEmpty(_currentModel.FileName))
            return;

        Uri fileUri = new Uri(_currentModel.FileName);
        if (!fileUri.Equals(this.xsltProcessor.CurrentBaseUri))
        {
            this.xsltProcessor.CurrentBaseUri = fileUri;
            this._fileListControl.BaseUri = fileUri;

            // KHÔI PHỤC đường dẫn đầu ra từ cache nếu có
            if (!string.IsNullOrEmpty(_currentModel.TransformOutputPath))
            {
                this.txtOutputPath.Text = ConvertToRelativePath(_currentModel.TransformOutputPath);
                this._outputManuallySet = true;
            }
            else
            {
                this.txtOutputPath.Text = string.Empty;
                this._outputManuallySet = false;
            }
        }

        // KHÔI PHỤC đường dẫn nguồn XSLT từ cache
        if (!string.IsNullOrEmpty(_currentModel.AssociatedXsltPath))
        {
            this.txtSourcePath.Text = _currentModel.AssociatedXsltPath;

            // Tự động chạy chuyển đổi nếu được bật
            if (_currentModel.EnableAutoTransform && this.IsControlVisible)
            {
                this._actionScheduler.Schedule("AutoTransform",
                    () => RenderTransformationResult(),
                    TimeSpan.FromMilliseconds(300));
            }
        }

        if (args.ModelChangeType == ModelChangeType.Reloaded && this.IsControlVisible)
        {
            this._actionScheduler.Schedule("UpdateXslt",
                () => RenderTransformationResult(),
                TimeSpan.FromSeconds(0.5));
        }
    }
    catch (Exception error)
    {
        System.Diagnostics.Debug.WriteLine($"XsltViewer model change error: {error.Message}");
    }
}

Thêm tùy chọn cấu hình cho người dùng

Cung cấp tùy chọn trong hộp thoại Settings để người dùng có thể bật/tắt tính năng tự động khôi phục liên kết.

// Trong lớp quản lý cài đặt (ví dụ: AppSettings.cs)
public class ApplicationSettings
{
    private bool _retainXsltOnReload;

    public ApplicationSettings()
    {
        // Đọc giá trị từ cấu hình, mặc định là true
        _retainXsltOnReload = LoadBooleanSetting("RetainXsltAssociation", true);
    }

    [DisplayName("Retain XSLT association on reload")]
    [Description("Preserves the linked XSLT file path when reloading the XML document.")]
    public bool RetainXsltAssociation
    {
        get { return _retainXsltOnReload; }
        set
        {
            _retainXsltOnReload = value;
            SaveSetting("RetainXsltAssociation", value);
        }
    }

    private bool LoadBooleanSetting(string key, bool defaultValue)
    {
        // Logic đọc từ file cấu hình hoặc registry
        // ...
    }
    private void SaveSetting(string key, bool value)
    {
        // Logic lưu vào file cấu hình hoặc registry
        // ...
    }
}

Sau đó, phương thức ReloadDocument trong XmlCache cần kiểm tra cài đặt này:

public void ReloadDocument()
{
    bool shouldPersist = _appSettings.RetainXsltAssociation;

    string xsltToRestore = null;
    string outputToRestore = null;

    if (shouldPersist)
    {
        xsltToRestore = this.AssociatedXsltPath;
        outputToRestore = this.TransformOutputPath;
    }

    // Logic tải lại tài liệu...

    if (shouldPersist)
    {
        this.AssociatedXsltPath = xsltToRestore;
        this.TransformOutputPath = outputToRestore;
    }
}

Đánh giá hiệu suất và quản lý bộ nhớ

Việc lưu trữ thêm một vài chuỗi đường dẫn có tác động không đáng kể đến bộ nhớ. Để tối ưu hơn, có thể sử dụng kỹ thuật khởi tạo lười (Lazy Initialization) cho cấu trúc lưu trữ trạng thái, đảm bảo tài nguyên chỉ được cấp phát khi cần.

private Lazy<XsltAssociationData> _xsltData = new Lazy<XsltAssociationData>(() => new XsltAssociationData());

public string AssociatedXsltPath
{
    get
    {
        // Chỉ truy cập Value nếu đã được khởi tạo
        return _xsltData.IsValueCreated ? _xsltData.Value.SourcePath : null;
    }
    private set
    {
        // Chỉ gán giá trị nếu đối tượng đã được khởi tạo hoặc giá trị mới khác null
        if (!_xsltData.IsValueCreated && value == null)
            return;
        _xsltData.Value.SourcePath = value;
    }
}

// Lớp chứa dữ liệu liên kết
private class XsltAssociationData
{
    public string SourcePath { get; set; }
    public string OutputPath { get; set; }
}

Ưu điểm của giải pháp

  • Tự động hóa: Loại bỏ thao tác thủ công lặp lại sau mỗi lần tải lại file.
  • Linh hoạt: Người dùng có thể tắt tính năng thông qua cài đặt.
  • Dễ mở rộng: Cấu trúc cho phép bổ sung thêm thông tin trạng thái như tham số XSLT, tùy chọn chuyển đổi.
  • Hiệu quả: Cải thiện đáng kể quy trình làm việc cho các tác vụ chỉnh sửa-xem trước lặp đi lặp lại hoặc khi làm việc với tài liệu XML lớn.

Thẻ: XmlNotepad XSLT XML .NET C#

Đăng vào ngày 5 tháng 9 lúc 05:19