// Copyright © Microsoft Corporation. // This source file is subject to the Microsoft Permissive License. // See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx. // All other rights reserved. using System; using System.Collections.Generic; using System.Configuration; using System.Xml; using System.Xml.XPath; namespace Microsoft.Ddue.Tools { public class CopyFromFileComponent : BuildComponent { public CopyFromFileComponent (BuildAssembler assembler, XPathNavigator configuration) : base(assembler, configuration) { if (configuration == null) throw new ArgumentNullException("configuration"); string data_name = null; // get information about the data file XPathNodeIterator data_nodes = configuration.Select("data"); foreach (XPathNavigator data_node in data_nodes) { string data_file = data_node.GetAttribute("file", String.Empty); if (String.IsNullOrEmpty(data_file)) WriteMessage(MessageLevel.Error, "Data elements must have a file attribute specifying a file from which to load data."); data_file = Environment.ExpandEnvironmentVariables(data_file); data_name = data_node.GetAttribute("name", String.Empty); if (String.IsNullOrEmpty(data_name)) data_name = Guid.NewGuid().ToString(); // load a schema, if one is specified string schema_file = data_node.GetAttribute("schema", String.Empty); XmlReaderSettings settings = new XmlReaderSettings(); if (!String.IsNullOrEmpty(schema_file)) { settings.Schemas.Add(null, schema_file); } // load the document WriteMessage(MessageLevel.Info, String.Format("Loading data file '{0}'.", data_file) ); using (XmlReader reader = XmlReader.Create(data_file, settings)) { XPathDocument data_document = new XPathDocument(reader); Data.Add(data_name, data_document); } } // get the source and target expressions for each copy command XPathNodeIterator copy_nodes = configuration.Select("copy"); foreach (XPathNavigator copy_node in copy_nodes) { string source_name = copy_node.GetAttribute("name", String.Empty); if (String.IsNullOrEmpty(source_name)) source_name = data_name; XPathDocument source_document = (XPathDocument) Data[source_name]; string source_xpath = copy_node.GetAttribute("source", String.Empty); if (String.IsNullOrEmpty(source_xpath)) throw new ConfigurationErrorsException("When instantiating a CopyFromFile component, you must specify a source xpath format using the source attribute."); string target_xpath = copy_node.GetAttribute("target", String.Empty); if (String.IsNullOrEmpty(target_xpath)) throw new ConfigurationErrorsException("When instantiating a CopyFromFile component, you must specify a target xpath format using the target attribute."); copy_commands.Add( new CopyFromFileCommand(source_document, source_xpath, target_xpath) ); } } // private XPathDocument data_document; private List copy_commands = new List(); private CustomContext context = new CustomContext(); // the work of the component public override void Apply (XmlDocument document, string key) { // set the key in the XPath context context["key"] = key; // iterate over the copy commands foreach (CopyFromFileCommand copy_command in copy_commands) { // extract the target node XPathExpression target_xpath = copy_command.Target.Clone(); target_xpath.SetContext(context); XPathNavigator target = document.CreateNavigator().SelectSingleNode(target_xpath); // warn if target not found? if (target == null) { continue; } // extract the source nodes XPathExpression source_xpath = copy_command.Source.Clone(); source_xpath.SetContext(context); XPathNodeIterator sources = copy_command.SourceDocument.CreateNavigator().Select(source_xpath); // warn if source not found? // append the source nodes to the target node foreach (XPathNavigator source in sources) { target.AppendChild(source); } } } } // a representation of a copying operation internal class CopyFromFileCommand { public CopyFromFileCommand (XPathDocument source_document, string source_xpath, string target_xpath) { this.source_document = source_document; source = XPathExpression.Compile(source_xpath); target = XPathExpression.Compile(target_xpath); } private XPathDocument source_document; private XPathExpression source; private XPathExpression target; public XPathDocument SourceDocument { get { return(source_document); } } public XPathExpression Source { get { return(source); } } public XPathExpression Target { get { return(target); } } } }