1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
// 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<CopyFromFileCommand> copy_commands = new List<CopyFromFileCommand>();
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);
}
}
}
}
|