/// <summary> /// Gets the XML from cache /// </summary> /// <param name="asp">Class containing all the search parameters.</param> /// <returns>Whether we have got the XML from the File Cache</returns> private bool GetArticleSearchCachedXml(ArticleSearchParams asp) { bool gotFromCache = false; _cacheName = "articlesearch-"; //Create a cache name including the site, keyphrases, dateranges, if any, skip and show params. _cacheName += asp.SiteID.ToString(); if (asp.ContentType != 0) { _cacheName += "-type" + asp.ContentType; } if (asp.ArticleStatus != 0) { _cacheName += "-artstatus" + asp.ArticleStatus; } if (asp.ArticleType != 0) { _cacheName += "-arttype" + asp.ArticleType; } if (asp.DateSearchType != 0) { _cacheName += "-datesearchtype-" + asp.DateSearchType; _cacheName += "-" + asp.StartDate.Year + "-" + asp.StartDate.Month + "-" + asp.StartDate.Day; _cacheName += "-" + asp.EndDate.Year + "-" + asp.EndDate.Month + "-" + asp.EndDate.Day; _cacheName += "-" + asp.TimeInterval; } _cacheName += (asp.Phrases.Length == 0 ? "" : "-") + asp.Phrases; _cacheName += (asp.NameSpaces.Length == 0 ? "" : "-") + asp.NameSpaces; if (asp.Latitude != 0.0 || asp.Longitude != 0.0 || asp.Range != 0.0) { _cacheName += "-lat" + asp.Latitude.ToString() + "-lon" + asp.Longitude.ToString() + "-rge" + asp.Range.ToString(); } if (asp.FreeTextSearchCondition != String.Empty) { _cacheName += "-" + asp.FreeTextSearchCondition; } _cacheName += "-" + asp.Skip + "-" + asp.Show + (asp.SortBy.Length == 0 ? "" : "-") + asp.SortBy; _cacheName += "-" + asp.SkipPhrases + "-" + asp.ShowPhrases; if (asp.DescendingOrder) { _cacheName += "-desc"; } else { _cacheName += "-asc"; } _cacheName += ".xml"; int articleSearchCacheTime = 10; try { articleSearchCacheTime = InputContext.GetSiteOptionValueInt("ArticleSearch", "CacheTime"); } catch (SiteOptionNotFoundException Ex) { InputContext.Diagnostics.WriteToLog("Article Search", Ex.Message); articleSearchCacheTime = 10; } if (articleSearchCacheTime < 10) { articleSearchCacheTime = 10; } //Try to get a cached copy. DateTime expiry = DateTime.Now - TimeSpan.FromMinutes(articleSearchCacheTime); // expire after x minutes set in the siteoptions string articleSearchXML = String.Empty; if (FileCache.GetItem(AppContext.TheAppContext.Config.CachePath, "articlesearch", _cacheName, ref expiry, ref articleSearchXML)) { RipleyAddInside(RootElement, articleSearchXML); gotFromCache = true; } return gotFromCache; }
/// <summary> /// With the returned data set generate the XML for the Article Search page /// </summary> /// <param name="dataReader">The returned search resultset</param> /// <param name="asp">The Article Search Params</param> private void GenerateArticleSearchXml(IDnaDataReader dataReader, ArticleSearchParams asp) { RootElement.RemoveAll(); XmlNode articleSearch = AddElementTag(RootElement, "ARTICLESEARCH"); AddAttribute(articleSearch, "CONTENTTYPE", asp.ContentType); AddAttribute(articleSearch, "SORTBY", asp.SortBy); AddAttribute(articleSearch, "SKIPTO", asp.Skip); AddAttribute(articleSearch, "SHOW", asp.Show); AddAttribute(articleSearch, "DATESEARCHTYPE", asp.DateSearchType); AddAttribute(articleSearch, "TIMEINTERVAL", asp.TimeInterval); AddAttribute(articleSearch, "ARTICLESTATUS", asp.ArticleStatus); AddAttribute(articleSearch, "ARTICLETYPE", asp.ArticleType); AddAttribute(articleSearch, "LATITUDE", asp.Latitude); AddAttribute(articleSearch, "LONGITUDE", asp.Longitude); AddAttribute(articleSearch, "RANGE", asp.Range); AddAttribute(articleSearch, "POSTCODE", asp.PostCode); AddAttribute(articleSearch, "PLACENAME", asp.Placename); AddAttribute(articleSearch, "LOCATIONSEARCHTYPE", asp.LocationSearchType); //Add the new descending order attribute if (asp.DescendingOrder) { AddAttribute(articleSearch, "DESCENDINGORDER", 1); } else { AddAttribute(articleSearch, "DESCENDINGORDER", 0); } //Add the requested searchphraselist GeneratePhraseXml(asp.SearchPhraseList, (XmlElement)articleSearch); //Add Date Search Params if we are doing a date search if (asp.DateSearchType != 0) { AddDateXml(asp.StartDate, articleSearch, "DATERANGESTART"); // Take a day from the end date as used in the database for UI purposes. // E.g. User submits a date range of 01/09/1980 to 02/09/1980. They mean for this to represent 2 days i.e. 01/09/1980 00:00 - 03/09/1980 00:00. // This gets used in the database but for display purposes we subtract a day from the database end date to return the // original dates submitted by the user inorder to match their expectations. AddDateXml(asp.EndDate.AddDays(-1), articleSearch, "DATERANGEEND"); } AddTextTag(articleSearch, "FREETEXTSEARCH", asp.FreeTextSearchCondition); XmlNode articles = AddElementTag(articleSearch, "ARTICLES"); int total = 0; int count = 0; //Generate Hot-List from Search Results. PopularPhrases popularPhrases = null; if (InputContext.GetSiteOptionValueBool("articlesearch", "generatepopularphrases")) { popularPhrases = new PopularPhrases(); } if (dataReader.HasRows) { // process first results set: the Article Key phrase results set Dictionary<int, ArrayList> articleKeyPhrases = new Dictionary<int, ArrayList>(); ArrayList phraselist = new ArrayList(); int h2g2ID = 0; if (dataReader.Read()) { int previousH2G2ID = 0; do { h2g2ID = dataReader.GetInt32NullAsZero("H2G2ID"); if (h2g2ID != previousH2G2ID) { //New now have a new article so clean up the last one if (previousH2G2ID != 0) { articleKeyPhrases.Add(previousH2G2ID, phraselist); phraselist = new ArrayList(); } } //set the previous h2g2id to this one previousH2G2ID = h2g2ID; //Create fill an new Phrase object Phrase nameSpacedPhrase = new Phrase(); String nameSpace = String.Empty; String phraseName = dataReader.GetStringNullAsEmpty("phrase"); if (phraseName != String.Empty) { if (dataReader.Exists("namespace")) { nameSpace = dataReader.GetStringNullAsEmpty("namespace"); } nameSpacedPhrase.NameSpace = nameSpace; nameSpacedPhrase.PhraseName = phraseName; //add it to the list phraselist.Add(nameSpacedPhrase); //Record Popular Phrases. if (popularPhrases != null) { popularPhrases.AddPhrase(phraseName, nameSpace); } } } while (dataReader.Read()); } articleKeyPhrases.Add(h2g2ID, phraselist); dataReader.NextResult(); if (dataReader.Read()) { total = dataReader.GetInt32NullAsZero("TOTAL"); //The stored procedure returns one row for each article. The article's keyphrases have been stored in articleKeyPhrases. XmlNode article = CreateElementNode("ARTICLE"); do { count++; h2g2ID = dataReader.GetInt32NullAsZero("H2G2ID"); //Start filling new article xml AddAttribute(article, "H2G2ID", h2g2ID); int editorID = dataReader.GetInt32NullAsZero("editor"); XmlNode editor = CreateElementNode("EDITOR"); User user = new User(InputContext); user.AddUserXMLBlock(dataReader, editorID, editor); article.AppendChild(editor); AddTextTag(article, "STATUS", dataReader.GetInt32NullAsZero("status")); AddXmlTextTag(article, "SUBJECT", dataReader.GetStringNullAsEmpty("SUBJECT")); AddTextTag(article, "TYPE", dataReader.GetInt32NullAsZero("type")); AddDateXml(dataReader, article, "DateCreated", "DATECREATED"); AddDateXml(dataReader, article, "LastUpdated", "LASTUPDATED"); //Add Extra Info XML where it exists. string extraInfo = dataReader.GetAmpersandEscapedStringNullAsEmpty("EXTRAINFO"); if (extraInfo != string.Empty) { XmlDocument extraInfoXml = new XmlDocument(); extraInfoXml.LoadXml(extraInfo); article.AppendChild(ImportNode(extraInfoXml.FirstChild)); } AddTextTag(article, "NUMBEROFPOSTS", dataReader.GetInt32NullAsZero("ForumPostCount")); AddDateXml(dataReader, article, "LASTPOSTED", "FORUMLASTPOSTED"); if (!dataReader.IsDBNull("StartDate")) { AddDateXml(dataReader, article, "StartDate", "DATERANGESTART"); // Take a day from the end date as stored in the database for UI purposes. // E.g. User submits a date range of 01/09/1980 to 02/09/1980. They mean for this to represent 2 days i.e. 01/09/1980 00:00 - 03/09/1980 00:00. // This gets stored in the database but for display purposes we subtract a day from the database end date to return the // original dates submitted by the user inorder to match their expectations. AddDateXml(dataReader.GetDateTime("EndDate").AddDays(-1), article, "DATERANGEEND"); AddTextTag(article, "TIMEINTERVAL", dataReader.GetInt32NullAsZero("TimeInterval")); } if (dataReader.DoesFieldExist("BookmarkCount")) { AddTextTag(article, "BOOKMARKCOUNT", dataReader.GetInt32NullAsZero("BookmarkCount")); } if (dataReader.DoesFieldExist("ZeitgeistScore")) { AddElement(article, "ZEITGEIST", "<SCORE>" + dataReader.GetDoubleNullAsZero("ZeitgeistScore") + "</SCORE>"); } #region LocationXML //*********************************************************************** // Location Info //*********************************************************************** if (dataReader.DoesFieldExist("Latitude") && !dataReader.IsDBNull("Latitude")) { AddTextTag(article, "LATITUDE", dataReader.GetDoubleNullAsZero("Latitude").ToString()); AddTextTag(article, "LONGITUDE", dataReader.GetDoubleNullAsZero("Longitude").ToString()); if (dataReader.DoesFieldExist("Distance")) { if (dataReader.GetDoubleNullAsZero("Distance") < 0.0001) { AddTextTag(article, "DISTANCE", "0"); } else { AddTextTag(article, "DISTANCE", dataReader.GetDoubleNullAsZero("Distance").ToString()); } } AddTextTag(article, "LOCATIONTITLE", dataReader.GetString("LocationTitle")); AddTextTag(article, "LOCATIONDESCRIPTION", dataReader.GetString("LocationDescription")); AddTextTag(article, "LOCATIONZOOMLEVEL", dataReader.GetInt32NullAsZero("LocationZoomLevel").ToString()); AddTextTag(article, "LOCATIONUSERID", dataReader.GetInt32NullAsZero("LocationUserID").ToString()); AddDateXml(dataReader.GetDateTime("LocationDateCreated"), article, "LOCATIONDATECREATED"); } //*********************************************************************** #endregion //*********************************************************************** // Media Asset Info //*********************************************************************** int mediaAssetID = dataReader.GetInt32NullAsZero("MediaAssetID"); if (mediaAssetID != 0) { AddMediaAssetXml(dataReader, article, mediaAssetID); } //*********************************************************************** AddPollXml(dataReader, article); if (articleKeyPhrases.ContainsKey(h2g2ID)) { GeneratePhraseXml(articleKeyPhrases[h2g2ID], (XmlElement)article); } XmlNode previousarticle = article.CloneNode(true); articles.AppendChild(previousarticle); article.RemoveAll(); } while (dataReader.Read()); } } articleSearch.AppendChild(articles); AddAttribute(articleSearch, "COUNT", count); AddAttribute(articleSearch, "TOTAL", total); if (popularPhrases != null) { //Include popularPhrase statistics. XmlElement popularPhrasesXml = popularPhrases.GenerateXml(); articleSearch.AppendChild(ImportNode(popularPhrasesXml)); } FileCache.PutItem(AppContext.TheAppContext.Config.CachePath, "articlesearch", _cacheName, articleSearch.OuterXml); //articleSearch.OwnerDocument.Save(@"c:\TEMP\Articlesearch.xml"); }
/// <summary> /// Calls the correct stored procedure given the inputs selected /// </summary> /// <param name="asp">Class containing all the search parameters.</param> private void GenerateArticleSearchPageXml(ArticleSearchParams asp) { using (IDnaDataReader dataReader = InputContext.CreateDnaDataReader("getarticles_dynamic")) { dataReader.AddParameter("siteid", asp.SiteID) .AddParameter("firstindex", asp.Skip + 1) //Added as row number starts at 1 .AddParameter("lastindex", asp.Skip + asp.Show); //Default sortbydatecreated. if (asp.SortBy == "Caption") { dataReader.AddParameter("sortbycaption", 1); } else if (asp.SortBy == "Rating") { dataReader.AddParameter("sortbyrating", 1); } else if (asp.SortBy == "StartDate") { dataReader.AddParameter("sortbystartdate", 1); } else if (asp.SortBy == "EndDate") { dataReader.AddParameter("sortbyenddate", 1); } else if (asp.SortBy == "ArticleZeitgeist") { dataReader.AddParameter("sortbyarticlezeitgeist", 1); } else if (asp.SortBy == "PostCount") { dataReader.AddParameter("sortbypostcount", 1); } else if (asp.SortBy == "Range") { dataReader.AddParameter("sortbyrange", 1); } else if (asp.SortBy == "BookmarkCount") { dataReader.AddParameter("sortbybookmarkcount", 1); } else if (asp.SortBy == "LastPosted") { dataReader.AddParameter("sortbylastposted", 1); } else if (asp.SortBy == "LastUpdated") { dataReader.AddParameter("sortbylastupdated", 1); } if (asp.Phrases != String.Empty) { dataReader.AddParameter("keyphraselist", asp.Phrases); } if (asp.NameSpaces != String.Empty) { dataReader.AddParameter("namespacelist", asp.NameSpaces); } if (asp.DateSearchType != 0 && asp.StartDate != DateTime.MinValue && asp.ContentType == -1) { dataReader.AddParameter("startdate", asp.StartDate); dataReader.AddParameter("enddate", asp.EndDate); //if (timeInterval > 0) //{ // dataReader.AddParameter("timeinterval", timeInterval); //} if (asp.DateSearchType == 2) { dataReader.AddParameter("touchingdaterange", 1); } } if (asp.ContentType != -1) { dataReader.AddParameter("assettype", asp.ContentType); } if (asp.ArticleStatus != 0) { dataReader.AddParameter("articlestatus", asp.ArticleStatus); } if (asp.ArticleType != 0) { dataReader.AddParameter("articletype", asp.ArticleType); } if (asp.DescendingOrder) { dataReader.AddParameter("descendingorder", 1); } else { dataReader.AddParameter("descendingorder", 0); } if (asp.Latitude != 0.0) { dataReader.AddParameter("latitude", asp.Latitude); dataReader.AddParameter("longitude", asp.Longitude); dataReader.AddParameter("range", asp.Range); } if (asp.FreeTextSearchCondition != String.Empty) { dataReader.AddParameter("freetextsearchcondition", asp.FreeTextSearchCondition); } dataReader.Execute(); GenerateArticleSearchXml(dataReader, asp); } }
/// <summary> /// Gets the params for the page /// </summary> /// <param name="asp">Class containing all the search parameters.</param> private bool TryGetPageParams(ref ArticleSearchParams asp) { int startDay = 0; int startMonth = 0; int startYear = 0; int endDay = 0; int endMonth = 0; int endYear = 0; string startDateText = String.Empty; string endDateText = String.Empty; //siteID = InputContext.GetParamIntOrZero("siteid", _docDnaSiteID); asp.SiteID = InputContext.CurrentSite.SiteID; int defaultShow = InputContext.GetSiteOptionValueInt("ArticleSearch", "DefaultShow"); asp.Skip = InputContext.GetParamIntOrZero("skip", _docDnaSkip); asp.Show = InputContext.GetParamIntOrZero("show", _docDnaShow); if (asp.Show > 200) { asp.Show = 200; } else if (asp.Show < 1) { asp.Show = defaultShow; } asp.SkipPhrases = InputContext.GetParamIntOrZero("skipphrases", _docDnaSkipPhrases); asp.ShowPhrases = InputContext.GetParamIntOrZero("showphrases", _docDnaShowPhrases); if (asp.ShowPhrases > 200) { asp.ShowPhrases = 200; } else if (asp.ShowPhrases < 1) { asp.ShowPhrases = defaultShow; } if (asp.SkipPhrases < 1) { asp.SkipPhrases = 0; } asp.ContentType = InputContext.GetParamIntOrZero("contenttype", _docDnaContentType); asp.SortBy = InputContext.GetParamStringOrEmpty("articlesortby", _docDnaArticleSortBy); asp.DateSearchType = InputContext.GetParamIntOrZero("datesearchtype", _docDnaDateSearchType); asp.TimeInterval = InputContext.GetParamIntOrZero("timeinterval", _docDnaTimeInterval); startDay = InputContext.GetParamIntOrZero("startDay", _docDnaStartDay); startMonth = InputContext.GetParamIntOrZero("startMonth", _docDnaStartMonth); startYear = InputContext.GetParamIntOrZero("startYear", _docDnaStartYear); endDay = InputContext.GetParamIntOrZero("endDay", _docDnaEndDay); endMonth = InputContext.GetParamIntOrZero("endMonth", _docDnaEndMonth); endYear = InputContext.GetParamIntOrZero("endYear", _docDnaEndYear); startDateText = InputContext.GetParamStringOrEmpty("startDate", _docDnaStartDate); endDateText = InputContext.GetParamStringOrEmpty("endDate", _docDnaEndDate); asp.ArticleStatus = InputContext.GetParamIntOrZero("articlestatus", _docDnaArticleStatus); asp.ArticleType = InputContext.GetParamIntOrZero("articletype", _docDnaArticleType); int descendingOrderNum = InputContext.GetParamIntOrZero("descendingorder", _docDnaDescendingOrder); if (descendingOrderNum == 1) { asp.DescendingOrder = true; } else { asp.DescendingOrder = false; } DateTime startDate; DateTime endDate; if (asp.DateSearchType != 0) { DateRangeValidation dateValidation = new DateRangeValidation(); DateRangeValidation.ValidationResult isValid; if (startDay == 0 && endDay == 0) { isValid = ParseDateParams(startDateText, endDateText, out startDate, out endDate); } else { isValid = ParseDateParams(startYear, startMonth, startDay, endYear, endMonth, endDay, out startDate, out endDate); } isValid = dateValidation.ValidateDateRange(startDate, endDate, asp.TimeInterval, false, false); if (isValid == DateRangeValidation.ValidationResult.VALID) { asp.StartDate = dateValidation.LastStartDate; asp.EndDate = dateValidation.LastEndDate; } else { return AddErrorXml("invalidparameters", "Illegal date parameters (" + isValid.ToString() + ")", null); } } //Get Search phrases. if (InputContext.DoesParamExist("phrase", _docDnaPhrase)) { asp.SearchPhraseList.Clear(); string rawPhrases = String.Empty; for (int i = 0; i < InputContext.GetParamCountOrZero("phrase", _docDnaPhrase); i++) { string phrase = InputContext.GetParamStringOrEmpty("phrase", i, _docDnaPhrase); if (phrase.Contains(_token)) { DnaStringParser paramParser = new DnaStringParser(phrase, _token.ToCharArray(), false, false, false); ArrayList paramPhraseList = paramParser.ParseToArrayList(); foreach (string paramPhrase in paramPhraseList) { rawPhrases = rawPhrases + paramPhrase + "|"; } } else { rawPhrases = rawPhrases + phrase + "|"; } } string rawNameSpaces = String.Empty; for (int i = 0; i < InputContext.GetParamCountOrZero("namespace", _docDnaNameSpace); i++) { string nameSpace = InputContext.GetParamStringOrEmpty("namespace", i, _docDnaNameSpace); if (nameSpace.Contains(_token)) { DnaStringParser paramParser = new DnaStringParser(nameSpace, _token.ToCharArray(), false, false, false); ArrayList paramNameList = paramParser.ParseToArrayList(); foreach (string paramNameSpace in paramNameList) { rawNameSpaces = rawNameSpaces + paramNameSpace + "|"; } } else { rawNameSpaces = rawNameSpaces + nameSpace + "|"; } } char[] charsToTrim = new char[] { '|' }; string parsedPhrases = String.Empty; //Now feed it into the DnaString Parser DnaStringParser phrasesParser = new DnaStringParser(rawPhrases, charsToTrim, true, true, false); parsedPhrases = phrasesParser.GetParsedString('|'); ArrayList searchPhraseList = phrasesParser.ParseToArrayList(); string parsedNameSpaces = String.Empty; //Now feed it into the DnaString Parser DnaStringParser nameSpaceParser = new DnaStringParser(rawNameSpaces, charsToTrim, true, true, false); parsedNameSpaces = nameSpaceParser.GetParsedString('|'); ArrayList searchNameSpaceList = nameSpaceParser.ParseToArrayList(); int phraseNumber = 0; foreach (string phraseText in searchPhraseList) { Phrase phrase = new Phrase(); phrase.PhraseName = phraseText; try { phrase.NameSpace = searchNameSpaceList[phraseNumber].ToString(); } catch (ArgumentOutOfRangeException) { phrase.NameSpace = ""; } asp.SearchPhraseList.Add(phrase); phraseNumber++; } asp.Phrases = parsedPhrases.TrimEnd(charsToTrim); asp.NameSpaces = parsedNameSpaces.TrimEnd(charsToTrim); } //Get (Postcode or Placename or Latitude and Longitude) and Range for Search if they are there. if (InputContext.DoesParamExist("postcode", _docDnaPostcode) || InputContext.DoesParamExist("placename", _docDnaPlacename) || (InputContext.DoesParamExist("latitude", _docDnaLatitude) && InputContext.DoesParamExist("longitude", _docDnaLongitude)) && InputContext.DoesParamExist("range", _docDnaRange)) { asp.Range = InputContext.GetParamDoubleOrZero("range", _docDnaRange); asp.LocationSearchType = InputContext.GetParamStringOrEmpty("locationsearchtype", _docDnaLocationSearchType); asp.PostCode = InputContext.GetParamStringOrEmpty("postcode", _docDnaPostcode); asp.Placename = InputContext.GetParamStringOrEmpty("placename", _docDnaPlacename); double latitude = InputContext.GetParamDoubleOrZero("latitude", _docDnaLatitude); double longitude = InputContext.GetParamDoubleOrZero("longitude", _docDnaLongitude); if (asp.LocationSearchType == "postcode") { GetLatLongFromPostCode(asp.PostCode, ref latitude, ref longitude); } else if (asp.LocationSearchType == "placename") { GetLatLongFromPlacename(asp.Placename, ref latitude, ref longitude); } asp.Latitude = latitude; asp.Longitude = longitude; } //Get free text search condition for Search if it is there. if (InputContext.DoesParamExist("freetextsearch", _docDnaFreeTextSearchCondition)) { asp.FreeTextSearchCondition = InputContext.GetParamStringOrEmpty("freetextsearch", _docDnaFreeTextSearchCondition); } return true; }
/// <summary> /// Method called to try the Article Search, gathers the input params, /// gets the correct records from the DB and formulates the XML /// </summary> /// <returns>Whether the search has suceeded with out error</returns> private bool TryArticleSearch() { ArticleSearchParams asp = new ArticleSearchParams(); bool pageParamsOK = TryGetPageParams(ref asp); if (!pageParamsOK) { return false; } bool cached = GetArticleSearchCachedXml(asp); if (!cached) { GenerateArticleSearchPageXml(asp); } bool generateHotlist = InputContext.GetSiteOptionValueBool("ArticleSearch", "GenerateHotlist"); if (generateHotlist) { bool cachedHotlist = GetArticleSearchHotlistCachedXml(); if (!cachedHotlist) { GenerateKeyPhraseHotlist(asp.SiteID, asp.SkipPhrases, asp.ShowPhrases, asp.ContentType, asp.SortBy, asp.DateSearchType, asp.Phrases); } } return true; }
/// <summary> /// Externally available Method called to try the Article Search, given the input params, /// gets the correct records from the DB and formulates the XML /// </summary> /// <param name="asp">Class containing all the search parameters.</param> public void DoArticleSearchWithParams(ArticleSearchParams asp) { bool cached = GetArticleSearchCachedXml(asp); cached = false; if (!cached) { GenerateArticleSearchPageXml(asp); } bool generateHotlist = InputContext.GetSiteOptionValueBool("ArticleSearch", "GenerateHotlist"); if (generateHotlist) { bool cachedHotlist = GetArticleSearchHotlistCachedXml(); if (!cachedHotlist) { GenerateKeyPhraseHotlist(asp.SiteID, asp.SkipPhrases, asp.ShowPhrases, asp.ContentType, asp.SortBy, asp.DateSearchType, asp.Phrases); } } }