/// <summary>
    /// Convert form fields pointing to a system property from an ID reference to a search
    /// </summary>
    private void FixFormFieldsPointingToSystemProperties(XmlDocument doc)
    {
      const string sysProps = "|behavior|classification|config_id|created_by_id|created_on|css|current_state|generation|history_id|id|is_current|is_released|keyed_name|release_date|effective_date|locked_by_id|major_rev|managed_by_id|minor_rev|modified_by_id|modified_on|new_version|not_lockable|owned_by_id|permission_id|related_id|sort_order|source_id|state|itemtype|superseded_date|team_id|";
      var fields = doc.ElementsByXPath("//Item[@type='Field'][contains($p0,concat('|',propertytype_id/@keyed_name,'|'))]", sysProps).ToList();
      if (fields.Count < 1) return;

      var query = "<Item type=\"Property\" action=\"get\" idlist=\"" + fields.GroupConcat(",", f => f.Element("propertytype_id", "")) + "\" select=\"name,source_id\" />";

      // Get all the property information from the database
      var results = _conn.Apply(query).Items().ToDictionary(e => e.Id(), e => new Command(
        @"<Item type='@0' action='get' select='id'>
            <name>@1</name>
            <source_id>@2</source_id>
        </Item>", e.Type().Value, e.Property("name").Value, e.SourceId().Value)
                .ToNormalizedAml(_conn.AmlContext.LocalizationContext));

      // Update the export the the proper edit scripts
      string propData;
      XmlDocument tempDoc;
      XmlElement propType;
      XmlElement parentItem;
      XmlElement script;
      foreach (var field in fields)
      {
        if (results.TryGetValue(field.Element("propertytype_id", ""), out propData))
        {
          propType = field.Element("propertytype_id");
          propType.RemoveAll();

          tempDoc = doc.NewDoc();
          tempDoc.LoadXml(propData);

          propType.AppendChild(propType.OwnerDocument.ImportNode(tempDoc.DocumentElement, true));
          propType.Detatch();
          parentItem = field.Parents().Last(e => e.LocalName == "Item");
          script = parentItem.OwnerDocument.CreateElement("Item")
            .Attr("type", field.Attribute("type"))
            .Attr("id", field.Attribute("id"))
            .Attr("action", "edit")
            .Attr(XmlFlags.Attr_ScriptType, "6");
          script.AppendChild(propType);
          parentItem.Parent().InsertAfter(script, parentItem);
        }
      }
    }
    /// <summary>
    /// Transform the results to normalize the output using the XSLT
    /// </summary>
    private XmlDocument TransformResults(ref XmlDocument results)
    {
      EnsureTransforms();

      var doc = results.NewDoc();
      // Transform the output
      ReportProgress(94, "Transforming the results");
      using (var memStream = new MemoryStream(results.DocumentElement.ChildNodes.Count * 1000))
      using (var output = new StreamWriter(memStream))
      {
        using (var reader = new XmlNodeReader(results.DocumentElement))
        {
          _resultTransform.Transform(reader, null, output);
        }
        // Nullify the original document immediately to reclaim the memory ASAP
        results = null;

        output.Flush();
        memStream.Position = 0;
        doc.Load(memStream);

      }

      // Make sure empty elements truly empty
      var emptyElements = doc.Descendants(e => !e.HasChildNodes && !e.IsEmpty).ToArray();
      foreach (var emptyElem in emptyElements)
      {
        emptyElem.IsEmpty = true;
      }

      return doc;
    }
    /// <summary>
    /// Execute the query to get all the relevant data from the database regarding the items to export.
    /// </summary>
    private XmlDocument ExecuteExportQuery(ref XmlDocument query, IEnumerable<ItemReference> itemRefs)
    {
      var itemDic = itemRefs.ToDictionary(i => i);
      var queryItems = query.DocumentElement.Elements("Item");
      var result = query.NewDoc();
      ReportProgress(4, "Searching for data...");

      var promises = queryItems.Select(q => (Func<IPromise>)(
          () => _conn.Process(q, true)
            .Convert(s => {
              return (IEnumerable<XmlElement>)(Items(result, s, itemDic).ToArray());
            })
          )
        ).ToArray();
      query = null; // Release the query memory as soon as possible;
      var items = Promises.Pooled(30, promises)
        .Progress((i, m) =>
        {
          ReportProgress(4 + (int)(i * 0.9), "Searching for data...");
        }).Wait();

      ReportProgress(95, "Loading results into memory...");
      var elems = items.SelectMany(r => (IEnumerable<XmlElement>)r);
      var root = result.Elem("Result");

      foreach (var elem in elems)
      {
        root.AppendChild(elem);
      }
      return result;
    }
 /// <summary>
 /// Normalize the formatting of class structure nodes to aid in manual line-based diff-ing
 /// </summary>
 private void NormalizeClassStructure(XmlDocument doc)
 {
   ReportProgress(97, "Transforming the results");
   var settings = new XmlWriterSettings();
   settings.OmitXmlDeclaration = true;
   settings.Indent = true;
   settings.IndentChars = "  ";
   var classStructs = (from e in doc.ElementsByXPath("//Item[@type='ItemType']/class_structure")
                       where !string.IsNullOrEmpty(e.InnerText)
                       select e);
   XmlDocument classDoc;
   foreach (var classStruct in classStructs)
   {
     classDoc = doc.NewDoc();
     var text = classStruct.InnerText;
     classDoc.LoadXml(text);
     var sb = new StringBuilder((int)(text.Length * 1.4));
     using (var output = new StringWriter(sb))
     {
       using (var writer = XmlTextWriter.Create(output, settings))
       {
         WriteClassStruct(Enumerable.Repeat((XmlNode)classDoc.DocumentElement, 1), writer);
       }
       classStruct.IsEmpty = true;
       classStruct.AppendChild(doc.CreateCDataSection(output.ToString()));
     }
   }
 }