public static void Main (string[] args) {

            TargetCollection targets = new TargetCollection();

            XPathDocument document = new XPathDocument(args[0]);
            XPathNavigator node = document.CreateNavigator();
            XmlTargetCollectionUtilities.AddTargets(targets, node, LinkType2.Local);
            Console.WriteLine(targets.Count);

            LinkTextResolver resolver = new LinkTextResolver(targets);

            // test writer
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            XmlWriter writer = XmlWriter.Create(Console.Out, settings);
            writer.WriteStartDocument();
            writer.WriteStartElement("types");
            XPathNodeIterator apiNodes = node.Select("/*/apis/api[not(apidata/@subgroup='enumeration')]//*[@display-api]");
            foreach (XPathNavigator apiNode in apiNodes) {
                string api = apiNode.GetAttribute("display-api", String.Empty);
                if (api[1] != ':') continue;

                string id = (string) apiNode.Evaluate("string(ancestor::api[1]/@id)");
                TextReferenceUtilities.SetGenericContext(id);

                Reference reference = TextReferenceUtilities.CreateReference(api);

                writer.WriteStartElement("test");
                writer.WriteAttributeString("api", api);
                writer.WriteAttributeString("context", id);
                if (reference == null) {
                    writer.WriteString("NULL REFERENCE");
                } else {
                    resolver.WriteReference(reference, DisplayOptions.ShowContainer | DisplayOptions.ShowTemplates | DisplayOptions.ShowParameters, writer);
                }
                writer.WriteEndElement();

            }

            writer.WriteEndElement();
            writer.WriteEndDocument();
            writer.Close();

        }
        internal static void WriteSimpleMemberReference (SimpleMemberReference member, DisplayOptions options, XmlWriter writer, LinkTextResolver resolver) {
            
            string cer = member.Id;

            string typeCer, memberName, arguments;
            DecomposeMemberIdentifier(cer, out typeCer, out memberName, out arguments);

            if ((options & DisplayOptions.ShowContainer) > 0) {
                SimpleTypeReference type = CreateSimpleTypeReference(typeCer);
                WriteSimpleTypeReference(type, options & ~DisplayOptions.ShowContainer, writer);
            }

            // change this so that we deal with EII names correctly, too
            writer.WriteString(memberName);

            if ((options & DisplayOptions.ShowParameters) > 0) {
                string[] parameterTypeCers;
                if (String.IsNullOrEmpty(arguments)) {
                    Parameter[] parameters = new Parameter[0];
                    resolver.WriteMethodParameters(parameters, writer);
                } else {
                    parameterTypeCers = SeperateTypes(arguments);
                    Parameter[] parameters = new Parameter[parameterTypeCers.Length];
                    for (int i = 0; i < parameterTypeCers.Length; i++) {
                        TypeReference parameterType = CreateTypeReference(parameterTypeCers[i]);
                        if (parameterType == null) {
                            parameterType = new NamedTemplateTypeReference("UAT");
                        }
                        parameters[i] = new Parameter(String.Empty, parameterType);
                    }
                    resolver.WriteMethodParameters(parameters, writer);
                }
            }

        }
        // instantiation logic 

        public ResolveReferenceLinksComponent2 (BuildAssembler assembler, XPathNavigator configuration)
            : base(assembler, configuration) {

            // base-url is an xpath expression applied against the current document to pick up the save location of the
            // document. If specified, local links will be made relative to the base-url.
            string baseUrlValue = configuration.GetAttribute("base-url", String.Empty);
            if (!String.IsNullOrEmpty(baseUrlValue))
                baseUrl = XPathExpression.Compile(baseUrlValue);

            // url-format is a string format that is used to format the value of local href attributes. The default is
            // "{0}.htm" for backwards compatibility.
            string hrefFormatValue = configuration.GetAttribute("href-format", String.Empty);
            if (!String.IsNullOrEmpty(hrefFormatValue))
                hrefFormat = hrefFormatValue;

            // the container XPath can be replaced; this is useful
            string containerValue = configuration.GetAttribute("container", String.Empty);
            if (!String.IsNullOrEmpty(containerValue)) XmlTargetCollectionUtilities.ContainerExpression = containerValue;

            targets = new TargetCollection();
            resolver = new LinkTextResolver(targets);

            XPathNodeIterator targets_nodes = configuration.Select("targets");
            foreach (XPathNavigator targets_node in targets_nodes) {

                // get target type
                string typeValue = targets_node.GetAttribute("type", String.Empty);
                if (String.IsNullOrEmpty(typeValue)) WriteMessage(MessageLevel.Error, "Each targets element must have a type attribute that specifies which type of links to create.");

                LinkType2 type = LinkType2.None;
                try {
                    type = (LinkType2)Enum.Parse(typeof(LinkType2), typeValue, true);
                    if ((type == LinkType2.Msdn) && (msdn == null)) {
                        WriteMessage(MessageLevel.Info, "Creating MSDN URL resolver.");
                        msdn = new MsdnResolver();
                    }
                } catch (ArgumentException) {
                    WriteMessage(MessageLevel.Error, String.Format("'{0}' is not a supported reference link type.", typeValue));
                }

                // get base directory
                string baseValue = targets_node.GetAttribute("base", String.Empty);

                // get file pattern
                string filesValue = targets_node.GetAttribute("files", String.Empty);
                if (String.IsNullOrEmpty(filesValue)) WriteMessage(MessageLevel.Error, "Each targets element must have a files attribute specifying which target files to load.");

                // determine whether to search recursively
                bool recurse = false;
                string recurseValue = targets_node.GetAttribute("recurse", String.Empty);
                if (!String.IsNullOrEmpty(recurseValue)) {
                    if (String.Compare(recurseValue, Boolean.TrueString, true) == 0) {
                        recurse = true;
                    } else if (String.Compare(recurseValue, Boolean.FalseString, true) == 0) {
                        recurse = false;
                    } else {
                        WriteMessage(MessageLevel.Error, String.Format("On the targets element, recurse='{0}' is not an allowed value.", recurseValue));
                    }
                }

                // turn baseValue and filesValue into directoryPath and filePattern
                string fullPath;
                if (String.IsNullOrEmpty(baseValue)) {
                    fullPath = filesValue;
                } else {
                    fullPath = Path.Combine(baseValue, filesValue);
                }
                fullPath = Environment.ExpandEnvironmentVariables(fullPath);
                string directoryPath = Path.GetDirectoryName(fullPath);
                if (String.IsNullOrEmpty(directoryPath)) directoryPath = Environment.CurrentDirectory;
                string filePattern = Path.GetFileName(fullPath);

                // verify that directory exists
                if (!Directory.Exists(directoryPath)) WriteMessage(MessageLevel.Error, String.Format("The targets directory '{0}' does not exist.", directoryPath));

                // add the specified targets from the directory
                WriteMessage(MessageLevel.Info, String.Format("Searching directory '{0}' for targets files of the form '{1}'.", directoryPath, filePattern));
                AddTargets(directoryPath, filePattern, recurse, type);

            }

            WriteMessage(MessageLevel.Info, String.Format("Loaded {0} reference targets.", targets.Count));

            string locale_value = configuration.GetAttribute("locale", String.Empty);
            if (!String.IsNullOrEmpty(locale_value) && msdn != null) msdn.Locale = locale_value;

            string target_value = configuration.GetAttribute("linkTarget", String.Empty);
            if (!String.IsNullOrEmpty(target_value)) linkTarget = target_value; 
        }