File: Tasks\Xdt\TransformXml.cs
Web Access
Project: ..\..\..\src\WebSdk\Publish\Tasks\Microsoft.NET.Sdk.Publish.Tasks.csproj (Microsoft.NET.Sdk.Publish.Tasks)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using Microsoft.Build.Framework;
using Microsoft.NET.Sdk.Publish.Tasks.MsDeploy;
using Microsoft.NET.Sdk.Publish.Tasks.Properties;
using Microsoft.Web.XmlTransform;
 
namespace Microsoft.NET.Sdk.Publish.Tasks.Xdt
{
    public class TransformXml : Task
    {
        private string? _sourceFile = null;
        private string? _transformFile = null;
        private string? _destinationFile = null;
        private string _sourceRootPath = string.Empty;
        private string _transformRootPath = string.Empty;
        private bool _ignoreError = false;
        private bool stackTrace = false;
 
        [Required]
        public string? Source
        {
            get
            {
                return Utility.GetFilePathResolution(_sourceFile, SourceRootPath);
            }
            set { _sourceFile = value; }
        }
 
        public string SourceRootPath
        {
            get { return _sourceRootPath; }
            set { _sourceRootPath = value; }
        }
 
        public bool IgnoreError
        {
            get { return _ignoreError; }
            set { _ignoreError = value; }
        }
 
        [Required]
        public string? Transform
        {
            get
            {
                return Utility.GetFilePathResolution(_transformFile, TransformRootPath);
            }
            set
            {
                _transformFile = value;
            }
        }
 
        public string TransformRootPath
        {
            get
            {
                if (string.IsNullOrEmpty(_transformRootPath))
                {
                    return SourceRootPath;
                }
                else
                {
                    return _transformRootPath;
                }
            }
            set { _transformRootPath = value; }
        }
 
        [Required]
        public string? Destination
        {
            get
            {
                return _destinationFile;
            }
            set
            {
                _destinationFile = value;
            }
        }
 
        public bool StackTrace
        {
            get
            {
                return stackTrace;
            }
            set
            {
                stackTrace = value;
            }
        }
 
        public override bool Execute()
        {
            return RunXmlTransform();
        }
 
        public bool RunXmlTransform(bool isLoggingEnabled = true)
        {
            bool succeeded = true;
            IXmlTransformationLogger? logger = null;
            if (isLoggingEnabled && !IgnoreError)
            {
                logger = new TaskTransformationLogger(Log, StackTrace);
            }
 
            XmlTransformation? transformation = null;
            XmlTransformableDocument? document = null;
 
            try
            {
                logger?.StartSection(string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.BUILDTASK_TransformXml_TransformationStart, Source));
                document = OpenSourceFile(Source);
 
                logger?.LogMessage(string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.BUILDTASK_TransformXml_TransformationApply, Transform));
                transformation = OpenTransformFile(Transform, logger);
 
                succeeded = transformation.Apply(document);
 
                if (succeeded)
                {
                    logger?.LogMessage(string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.BUILDTASK_TransformXml_TransformOutput, Destination));
 
                    SaveTransformedFile(document, Destination);
                }
 
                if (IgnoreError)
                {
                    return true;
                }
            }
            catch (System.Xml.XmlException ex)
            {
                if (IgnoreError)
                {
                    return true;
                }
 
                string? localPath = Source;
                if (!string.IsNullOrEmpty(ex.SourceUri))
                {
                    Uri sourceUri = new(ex.SourceUri);
                    localPath = sourceUri.LocalPath;
                }
 
                logger?.LogError(localPath, ex.LineNumber, ex.LinePosition, ex.Message);
                succeeded = false;
            }
            catch (Exception ex)
            {
                if (IgnoreError)
                {
                    return true;
                }
 
                logger?.LogErrorFromException(ex);
                succeeded = false;
            }
            finally
            {
                logger?.EndSection(string.Format(System.Globalization.CultureInfo.CurrentCulture, succeeded ?
                    Resources.BUILDTASK_TransformXml_TransformationSucceeded :
                    Resources.BUILDTASK_TransformXml_TransformationFailed));
                if (transformation != null)
                {
                    transformation.Dispose();
                }
                if (document != null)
                {
                    document.Dispose();
                }
            }
 
            return succeeded;
        }
 
        private void SaveTransformedFile(XmlTransformableDocument document, string? destinationFile)
        {
            try
            {
                document.Save(destinationFile);
            }
            catch (System.Xml.XmlException)
            {
                throw;
            }
            catch (Exception ex)
            {
                throw new Exception(
                    string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.BUILDTASK_TransformXml_DestinationWriteFailed, ex.Message),
                    ex);
            }
        }
 
        private XmlTransformableDocument OpenSourceFile(string? sourceFile)
        {
            try
            {
                XmlTransformableDocument document = new()
                {
                    PreserveWhitespace = true
                };
                document.Load(sourceFile);
 
                return document;
            }
            catch (System.Xml.XmlException)
            {
                throw;
            }
            catch (Exception ex)
            {
                throw new Exception(
                    string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.BUILDTASK_TransformXml_SourceLoadFailed, ex.Message),
                    ex);
            }
        }
 
        private XmlTransformation OpenTransformFile(string? transformFile, IXmlTransformationLogger? logger)
        {
            try
            {
                return new XmlTransformation(transformFile, logger);
            }
            catch (System.Xml.XmlException)
            {
                throw;
            }
            catch (Exception ex)
            {
                throw new Exception(
                    string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.BUILDTASK_TransformXml_TransformLoadFailed, ex.Message),
                    ex);
            }
        }
    }
}