private void AddTargets (string map, string input, string baseOutputPath, XPathExpression outputXPath, string link, XPathExpression formatXPath, XPathExpression relativeToXPath) {

			XPathDocument document = new XPathDocument(map);

			XPathNodeIterator items = document.CreateNavigator().Select("/*/item");
			foreach (XPathNavigator item in items) {

				string id = (string) item.Evaluate(artIdExpression);
				string file = (string) item.Evaluate(artFileExpression);
				string text = (string) item.Evaluate(artTextExpression);

				id = id.ToLower();
				string name = Path.GetFileName(file);

				ArtTarget target = new ArtTarget();
				target.Id = id;
				target.InputPath = Path.Combine(input, file);
				target.baseOutputPath = baseOutputPath;
                target.OutputXPath = outputXPath;
                
                if (string.IsNullOrEmpty(name)) target.LinkPath = link;
                else target.LinkPath = string.Format("{0}/{1}", link, name);
                
				target.Text = text;
                target.Name = name;
                target.FormatXPath = formatXPath;
                target.RelativeToXPath = relativeToXPath;

				targets[id] = target;
				// targets.Add(id, target);
            }

	    }
        private void AddTargets(string map, string input, string baseOutputPath, XPathExpression outputXPath, string link, XPathExpression formatXPath, XPathExpression relativeToXPath)
        {
            XPathDocument document = new XPathDocument(map);

            XPathNodeIterator items = document.CreateNavigator().Select("/*/item");

            foreach (XPathNavigator item in items)
            {
                string id   = (string)item.Evaluate(artIdExpression);
                string file = (string)item.Evaluate(artFileExpression);
                string text = (string)item.Evaluate(artTextExpression);

                id = id.ToLower();
                string name = Path.GetFileName(file);

                ArtTarget target = new ArtTarget();
                target.Id             = id;
                target.InputPath      = Path.Combine(input, file);
                target.baseOutputPath = baseOutputPath;
                target.OutputXPath    = outputXPath;

                if (string.IsNullOrEmpty(name))
                {
                    target.LinkPath = link;
                }
                else
                {
                    target.LinkPath = string.Format("{0}/{1}", link, name);
                }

                target.Text            = text;
                target.Name            = name;
                target.FormatXPath     = formatXPath;
                target.RelativeToXPath = relativeToXPath;

                targets[id] = target;
                // targets.Add(id, target);
            }
        }
        //=====================================================================

        /// <inheritdoc />
        public override void Initialize(XPathNavigator configuration)
        {
            XPathExpression artIdExpression   = XPathExpression.Compile("string(@id)"),
                            artFileExpression = XPathExpression.Compile("string(image/@file)"),
                            artTextExpression = XPathExpression.Compile("string(image/altText)");

            XPathNodeIterator targetsNodes = configuration.Select("targets");

            foreach (XPathNavigator targetsNode in targetsNodes)
            {
                // Get the configuration values for this target
                string inputPath = targetsNode.GetAttribute("input", String.Empty);

                if (String.IsNullOrEmpty(inputPath))
                {
                    base.WriteMessage(MessageLevel.Error, "Each targets element must have an input attribute " +
                                      "specifying a directory containing art files.");
                }

                inputPath = Environment.ExpandEnvironmentVariables(inputPath);

                if (!Directory.Exists(inputPath))
                {
                    base.WriteMessage(MessageLevel.Error, "The art input directory '{0}' does not exist.",
                                      inputPath);
                }

                string baseOutputPath = targetsNode.GetAttribute("baseOutput", String.Empty);

                if (!String.IsNullOrEmpty(baseOutputPath))
                {
                    baseOutputPath = Path.GetFullPath(Environment.ExpandEnvironmentVariables(baseOutputPath));
                }

                string outputPathValue = targetsNode.GetAttribute("outputPath", string.Empty);

                if (string.IsNullOrEmpty(outputPathValue))
                {
                    base.WriteMessage(MessageLevel.Error, "Each targets element must have an output attribute " +
                                      "specifying a directory in which to place referenced art files.");
                }

                XPathExpression outputXPath = XPathExpression.Compile(outputPathValue);

                string linkPath = targetsNode.GetAttribute("link", String.Empty);

                if (String.IsNullOrEmpty(linkPath))
                {
                    linkPath = "../art";
                }

                string map = targetsNode.GetAttribute("map", String.Empty);

                if (String.IsNullOrEmpty(map))
                {
                    base.WriteMessage(MessageLevel.Error, "Each targets element must have a map attribute " +
                                      "specifying a file that maps art IDs to files in the input directory.");
                }

                map = Environment.ExpandEnvironmentVariables(map);

                if (!File.Exists(map))
                {
                    base.WriteMessage(MessageLevel.Error, "The art map file '{0}' does not exist.", map);
                }

                string format = targetsNode.GetAttribute("format", String.Empty);

                XPathExpression formatXPath = String.IsNullOrEmpty(format) ? null :
                                              XPathExpression.Compile(format);

                string relativeTo = targetsNode.GetAttribute("relative-to", String.Empty);

                XPathExpression relativeToXPath = String.IsNullOrEmpty(relativeTo) ? null :
                                                  XPathExpression.Compile(relativeTo);

                // Load the content of the media map file
                XPathDocument     mediaMap = new XPathDocument(map);
                XPathNodeIterator items    = mediaMap.CreateNavigator().Select("/*/item");

                foreach (XPathNavigator item in items)
                {
                    string id   = (string)item.Evaluate(artIdExpression);
                    string file = (string)item.Evaluate(artFileExpression);
                    string text = (string)item.Evaluate(artTextExpression);
                    string name = Path.GetFileName(file);

                    targets[id] = new ArtTarget
                    {
                        InputPath       = Path.Combine(inputPath, file),
                        BaseOutputPath  = baseOutputPath,
                        OutputXPath     = outputXPath,
                        LinkPath        = String.IsNullOrEmpty(name) ? linkPath : String.Concat(linkPath, "/", name),
                        Text            = text,
                        Name            = name,
                        FormatXPath     = formatXPath,
                        RelativeToXPath = relativeToXPath
                    };
                }
            }

            base.WriteMessage(MessageLevel.Info, "Indexed {0} art targets.", targets.Count);
        }
        public override void Apply(XmlDocument document, string id)
        {
            XPathNodeIterator artLinkIterator = document.CreateNavigator().Select(artLinkExpression);

            XPathNavigator[] artLinks = BuildComponentUtilities.ConvertNodeIteratorToArray(artLinkIterator);
            foreach (XPathNavigator artLink in artLinks)
            {
                string name = artLink.GetAttribute("target", String.Empty).ToLower();

                if (targets.ContainsKey(name))
                {
                    ArtTarget target = targets[name];

                    // evaluate the path
                    string path = document.CreateNavigator().Evaluate(target.OutputXPath).ToString();

                    if (target.baseOutputPath != null)
                    {
                        path = Path.Combine(target.baseOutputPath, path);
                    }
                    string outputPath = Path.Combine(path, target.Name);

                    string targetDirectory = Path.GetDirectoryName(outputPath);

                    if (!Directory.Exists(targetDirectory))
                    {
                        Directory.CreateDirectory(targetDirectory);
                    }

                    if (File.Exists(target.InputPath))
                    {
                        if (File.Exists(outputPath))
                        {
                            File.SetAttributes(outputPath, FileAttributes.Normal);
                        }

                        File.Copy(target.InputPath, outputPath, true);
                    }
                    else
                    {
                        WriteMessage(MessageLevel.Warn, String.Format("The file '{0}' for the art target '{1}' was not found.", target.InputPath, name));
                    }

                    // Get the relative art path for HXF generation.
                    int    index   = target.LinkPath.IndexOf('/');
                    string artPath = target.LinkPath.Substring(index + 1, target.LinkPath.Length - (index + 1));

                    FileCreatedEventArgs fe = new FileCreatedEventArgs(artPath, Path.GetDirectoryName(path));
                    OnComponentEvent(fe);

                    XmlWriter writer = artLink.InsertAfter();

                    writer.WriteStartElement("img");
                    if (!String.IsNullOrEmpty(target.Text))
                    {
                        writer.WriteAttributeString("alt", target.Text);
                    }

                    if (target.FormatXPath == null)
                    {
                        writer.WriteAttributeString("src", target.LinkPath);
                    }
                    else
                    {
                        // WebDocs way, which uses the 'format' xpath expression to calculate the target path
                        // and then makes it relative to the current page if the 'relative-to' attribute is
                        // used.
                        string src = BuildComponentUtilities.EvalXPathExpr(document, target.FormatXPath, "key", Path.GetFileName(outputPath));
                        if (target.RelativeToXPath != null)
                        {
                            src = BuildComponentUtilities.GetRelativePath(src, BuildComponentUtilities.EvalXPathExpr(document, target.RelativeToXPath, "key", id));
                        }
                        writer.WriteAttributeString("src", src);
                    }

                    writer.WriteEndElement();

                    writer.Close();

                    artLink.DeleteSelf();
                }
                else
                {
                    WriteMessage(MessageLevel.Warn, String.Format("Unknown art target '{0}'", name));
                }
            }
        }